Annotation of Examples/DriverKit/SoundBlaster8/SoundBlaster8_reloc.tproj/SoundBlaster8.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved. 
        !             3:  *
        !             4:  * HISTORY
        !             5:  * 4-Mar-94    Rakesh Dubey at NeXT
        !             6:  *      Created. 
        !             7:  */
        !             8: 
        !             9: #import "SoundBlaster8.h"
        !            10: #import "SoundBlaster8Registers.h"
        !            11: 
        !            12: #import <driverkit/generalFuncs.h>
        !            13: 
        !            14: static const char codecDeviceName[] = "SoundBlaster8";
        !            15: static const char codecDeviceKind[] = "Audio";
        !            16: 
        !            17: static  sbCardParameters_t sbCardType;         // hardware type
        !            18: static  BOOL lowSpeedDMA;                      // different programming
        !            19: 
        !            20: /*
        !            21:  * Include inline functions. 
        !            22:  */
        !            23: #import "SoundBlaster8Inline.h"
        !            24: 
        !            25: @implementation SoundBlaster8
        !            26: 
        !            27: /*
        !            28:  * Probe and initialize new instance 
        !            29:  */
        !            30: + (BOOL) probe:deviceDescription
        !            31: {
        !            32:     SoundBlaster8       *dev;
        !            33:     IORange             *portRangeList;
        !            34:     int                 numPortRanges;
        !            35:     unsigned int        baseAddress;
        !            36: 
        !            37: #ifdef DEBUG
        !            38:     int                 i;
        !            39: #endif DEBUG
        !            40:  
        !            41:     dev = [self alloc];
        !            42:     if (dev == nil)
        !            43:         return NO;
        !            44: 
        !            45:     portRangeList = [deviceDescription portRangeList];
        !            46:     numPortRanges = [deviceDescription numPortRanges];
        !            47:     
        !            48:     if (numPortRanges < 1)
        !            49:        return NO;
        !            50: 
        !            51: #ifdef DEBUG
        !            52:     for (i=0; i < numPortRanges; i++) {
        !            53:         IOLog("SoundBlaster8: port %x %d\n",
        !            54:                 portRangeList[i].start, portRangeList[i].size);
        !            55:     }
        !            56: #endif DEBUG
        !            57: 
        !            58:     baseAddress = portRangeList[0].start;
        !            59: #ifdef DEBUG
        !            60:     IOLog("SoundBlaster8: Base address = 0x%x.\n", baseAddress);
        !            61: #endif DEBUG
        !            62: 
        !            63: 
        !            64:     /*
        !            65:      * Check base address to verify if this is a legal address.
        !            66:      */
        !            67: 
        !            68:     if ((baseAddress == SB_BASE_ADDRESS_1) ||
        !            69:         (baseAddress == SB_BASE_ADDRESS_2) ||
        !            70:         (baseAddress == SB_BASE_ADDRESS_3) ||
        !            71:         (baseAddress == SB_BASE_ADDRESS_4) ||
        !            72:         (baseAddress == SB_BASE_ADDRESS_5) ||
        !            73:         (baseAddress == SB_BASE_ADDRESS_6))     {
        !            74:         sbBaseRegisterAddress = baseAddress;
        !            75:     } else {
        !            76:         IOLog("SoundBlaster8: Invalid port address 0x%0x.\n", baseAddress);
        !            77:         [dev free];
        !            78:         return NO;
        !            79:     }
        !            80: 
        !            81:     /*
        !            82:      * Now assign all SB DSP and Mixer registers their addresses.
        !            83:      */
        !            84:     assignDSPRegAddresses();
        !            85:     assignMixerRegAddresses();
        !            86:     
        !            87:     return [dev initFromDeviceDescription:deviceDescription] != nil;
        !            88: }
        !            89: 
        !            90: 
        !            91: - (BOOL)reset
        !            92: {
        !            93:     unsigned int channel        = [[self deviceDescription] channel];
        !            94:     unsigned int interrupt      = [[self deviceDescription] interrupt];
        !            95: 
        !            96:     IOReturn ioReturn;
        !            97: 
        !            98:     [self setName:codecDeviceName];
        !            99:     [self setDeviceKind:codecDeviceKind];
        !           100: 
        !           101:     /*
        !           102:      * Are user selections valid?
        !           103:      */
        !           104:     if (checkSelectedDMAAndIRQ(channel, interrupt) == NO) {
        !           105:        return NO;
        !           106:     }
        !           107:     
        !           108:     /*
        !           109:      * Now that all hardware parameters have been assigned and/or verified
        !           110:      * initialize the hardware.
        !           111:      */
        !           112:     [self initializeHardware];
        !           113: 
        !           114:     /*
        !           115:      * This driver is only for 8-bit Sound Blaster cards. If this is not one
        !           116:      * of these systems we quit since the test is fully reliable.
        !           117:      */
        !           118:     
        !           119:     switch (sbCardType.version) {
        !           120:       case SB_CLASSIC:
        !           121:         sbCardType.name = "Classic";
        !           122:         break;
        !           123:       case SB_20:
        !           124:         sbCardType.name = "2.0";
        !           125:         break;
        !           126:       case SB_PRO:
        !           127:         sbCardType.name = "Pro";
        !           128:         break;
        !           129:       case SB_16:
        !           130:         sbCardType.name = "Pro";
        !           131:         sbCardType.version = SB_PRO;    /* SB16 will emulate it */
        !           132:         break;
        !           133:       default:  {
        !           134:         IOLog("SoundBlaster8: Hardware not detected at port 0x%0x.\n",
        !           135:                sbBaseRegisterAddress);
        !           136:         return NO;
        !           137:       }
        !           138:     }
        !           139:     
        !           140:     IOLog("SoundBlaster8: Sound Blaster %s (ver %d.%d) at port 0x%0x.\n", 
        !           141:                 sbCardType.name, 
        !           142:                 sbCardType.majorVersion, sbCardType.minorVersion, 
        !           143:                 sbBaseRegisterAddress);
        !           144:     
        !           145:     /*
        !           146:      * Initialize DMA controller.
        !           147:      */
        !           148:      
        !           149:     [self disableChannel: 0];
        !           150: 
        !           151:     /*
        !           152:      * This call is only applicable in EISA systems. All dma channels
        !           153:      * that are available to this driver in ISA machines are 8-bit. So we do
        !           154:      * this setup only for EISA machines. 
        !           155:      */
        !           156:     if ([self isEISAPresent]) {
        !           157:         ioReturn = [self setDMATransferWidth:IO_8Bit forChannel:0];
        !           158:         if (ioReturn != IO_R_SUCCESS) {
        !           159:             IOLog("SoundBlaster8: could not set transfer width to 8 bits, error %d.\n", ioReturn);
        !           160:             return NO;
        !           161:         }
        !           162:     }
        !           163:     
        !           164:     ioReturn = [self setTransferMode: IO_Single forChannel: 0];
        !           165:     if (ioReturn != IO_R_SUCCESS)  {
        !           166:         IOLog("%s: dma transfer mode error %d\n", [self name], ioReturn);
        !           167:         return NO;
        !           168:     }
        !           169: 
        !           170:     /*
        !           171:      * We will program the DMA controller in auto-init mode but the card is
        !           172:      * in single cycle mode. So at every interrupt we only need to reprogram
        !           173:      * the card.
        !           174:      */
        !           175:     ioReturn = [self setAutoinitialize: YES forChannel: 0];
        !           176:     if (ioReturn != IO_R_SUCCESS) {
        !           177:         IOLog("%s: dma auto initialize error %d", [self name], ioReturn);
        !           178:         return NO;
        !           179:     }
        !           180:     
        !           181:     return YES;
        !           182: }
        !           183: 
        !           184: 
        !           185: - (void) initializeHardware
        !           186: {
        !           187:     resetHardware();
        !           188: }
        !           189: 
        !           190: /*
        !           191:  * Converts gain (0 - 32768) into hardware supported gain (0 - 7). If the
        !           192:  * input source is line (not supported now), simply double the gain. 
        !           193:  */
        !           194: 
        !           195: - (void)updateInputGainLeft
        !           196: {
        !           197:     unsigned int gain = [self inputGainLeft];
        !           198:     unsigned int left  = 0;
        !           199:     
        !           200:     if (gain)
        !           201:         left = ((gain * MAX_INPUT_GAIN_MICROPHONE)/32768);
        !           202:     else
        !           203:         left = gain;    // minimum input gain = 0
        !           204:         
        !           205:     setInputGain(LEFT_CHANNEL, left);
        !           206: #ifdef DEBUG
        !           207:     IOLog("%s: updateInputGainLeft %d based on gain %d\n", [self name],left, gain);
        !           208: #endif DEBUG
        !           209: }
        !           210: 
        !           211: /*
        !           212:  * Converts gain (0 - 32768) into hardware supported gain (0 - 7)
        !           213:  */
        !           214: 
        !           215: - (void)updateInputGainRight
        !           216: {
        !           217:     unsigned int gain = [self inputGainRight];
        !           218:     unsigned int right = 0;
        !           219:     
        !           220:     if (gain)
        !           221:         right = ((gain * MAX_INPUT_GAIN_MICROPHONE)/32768);
        !           222:     else
        !           223:         right = gain;   // minimum input gain = 0
        !           224:         
        !           225:     setInputGain(RIGHT_CHANNEL, right);
        !           226: #ifdef DEBUG
        !           227:     IOLog("%s: updateInputGainRight %d based on gain %d\n", [self name], right, gain);
        !           228: #endif DEBUG
        !           229: }
        !           230: 
        !           231: - (void)updateOutputMute
        !           232: {
        !           233:     enableAudioOutput(! [self isOutputMuted]);
        !           234: }
        !           235: 
        !           236: /*
        !           237:  * (0) - (-84) needs to be converted to hardware supported (0) - (15)
        !           238:  */
        !           239: - (void) updateOutputAttenuationLeft
        !           240: {
        !           241:     unsigned int attenuation = [self outputAttenuationLeft] + 84;
        !           242:     unsigned int left = 0;
        !           243:     
        !           244:     left = ((attenuation * MAX_MASTER_OUTPUT_VOLUME)/84);
        !           245:    
        !           246:     setOutputAttenuation(LEFT_CHANNEL, left);
        !           247:     
        !           248: #ifdef DEBUG
        !           249:     IOLog("%s: converted la: %d into %d\n", [self name], attenuation, left);
        !           250: #endif DEBUG
        !           251: }
        !           252: 
        !           253: /*
        !           254:  * (0) - (-84) needs to be converted to hardware supported (0) - (15)
        !           255:  */
        !           256: - (void) updateOutputAttenuationRight
        !           257: {
        !           258:     unsigned int attenuation = [self outputAttenuationRight] + 84;
        !           259:     unsigned int right = 0;
        !           260:     
        !           261:     right = ((attenuation * MAX_MASTER_OUTPUT_VOLUME)/84);
        !           262:     
        !           263:     setOutputAttenuation(RIGHT_CHANNEL, right);
        !           264:    
        !           265: #ifdef DEBUG
        !           266:     IOLog("SoundBlaster8: converted ra: %d into %d\n", attenuation, right);
        !           267: #endif DEBUG
        !           268: }
        !           269: 
        !           270: /*
        !           271:  * Program DSP.
        !           272:  */
        !           273: - (void)updateSampleRate
        !           274: {
        !           275:     unsigned int rate;
        !           276:     unsigned int mode;
        !           277:     
        !           278:     rate = [self sampleRate];
        !           279:     mode = ([self channelCount] == 2) ? DSP_STEREO_MODE : DSP_MONO_MODE;
        !           280: 
        !           281:     /*
        !           282:      * Programming sequence depends upon whether we are doing a low speed or
        !           283:      * high speed transfer. Rather messy, see SB SDK page 12-5.
        !           284:      */
        !           285:     if (sbCardType.version == SB_CLASSIC) {
        !           286:        lowSpeedDMA = YES;
        !           287:     } else if (sbCardType.version == SB_20) {
        !           288:        if (currentDMADirection == DMA_DIRECTION_IN)
        !           289:            lowSpeedDMA = (rate < SB_20_LOW_SPEED_RECORD) ? YES : NO;
        !           290:        else
        !           291:            lowSpeedDMA = (rate < SB_20_LOW_SPEED_PLAYBACK) ? YES : NO;
        !           292:     } else if (sbCardType.version == SB_PRO) {
        !           293:         if (mode == DSP_STEREO_MODE)
        !           294:            rate *= 2;
        !           295:        lowSpeedDMA = (rate < SB_PRO_LOW_SPEED) ? YES : NO;
        !           296:     }
        !           297:     
        !           298:     setCodecDataMode(mode, currentDMADirection);
        !           299:     setCodecSamplingRate(rate);
        !           300: }
        !           301: 
        !           302: 
        !           303: /*
        !           304:  * Sets the DMA Counter Load register which decides when the next interrupt
        !           305:  * will arrive.
        !           306:  */
        !           307: - (void) setBufferCount:(int)count
        !           308: {
        !           309:     setSampleBufferCounter(count);      
        !           310: }
        !           311: 
        !           312: 
        !           313: - (IOReturn) enableAllInterrupts
        !           314: {
        !           315:     enableCodecInterrupts();
        !           316:     return [super enableAllInterrupts];
        !           317: }
        !           318: 
        !           319: - (void) disableAllInterrupts
        !           320: {
        !           321:    disableCodecInterrupts();
        !           322:    [super disableAllInterrupts];
        !           323: }
        !           324: 
        !           325: /*
        !           326:  * Return NO if the hardware does not support this particular playback/record
        !           327:  * request. The parameter scheme in soundkit does not fit the anarchy
        !           328:  * of PC world very well.
        !           329:  */
        !           330: - (BOOL)isValidRequest: (BOOL)isRead
        !           331: {
        !           332:     unsigned int rate;
        !           333:     unsigned int mode;
        !           334:     unsigned int encoding;
        !           335:     
        !           336:     rate = [self sampleRate];
        !           337:     encoding = [self dataEncoding];
        !           338:     mode = ([self channelCount] == 2) ? DSP_STEREO_MODE : DSP_MONO_MODE;
        !           339: 
        !           340: #ifdef DEBUG
        !           341:     IOLog("SoundBlaster8: rate: %d ", rate);
        !           342:     
        !           343:     if (mode == DSP_MONO_MODE)
        !           344:         IOLog("dataMode: mono ");
        !           345:     else if (mode == DSP_STEREO_MODE)
        !           346:         IOLog("dataMode: stereo ");
        !           347:     else
        !           348:         IOLog("dataMode: unknown ");
        !           349:         
        !           350:     if (encoding == NX_SoundStreamDataEncoding_Linear16)
        !           351:         IOLog("dataEncoding: linear 16\n");
        !           352:     else if (encoding == NX_SoundStreamDataEncoding_Linear8)
        !           353:         IOLog("dataEncoding: linear 8\n");
        !           354:     else if (encoding == NX_SoundStreamDataEncoding_Mulaw8)
        !           355:         IOLog("dataEncoding: mulaw 8\n");
        !           356:     else if (encoding == NX_SoundStreamDataEncoding_Alaw8)
        !           357:         IOLog("dataEncoding: Alaw 8\n");
        !           358:     else
        !           359:         IOLog("dataEncoding: unknown\n");
        !           360: #endif DEBUG
        !           361:        
        !           362:     if (sbCardType.version == SB_PRO) {
        !           363:         if ((mode == DSP_STEREO_MODE) &&
        !           364:             (rate > SB_PRO_LOW_SPEED))
        !           365:             return NO;          
        !           366:     }
        !           367:     
        !           368:     if (sbCardType.version == SB_20) {
        !           369:        if (isRead && rate > SB_20_LOW_SPEED_RECORD)
        !           370:            return NO;
        !           371:     }
        !           372:                 
        !           373:     if (sbCardType.version == SB_CLASSIC) {
        !           374:        if (isRead && rate > SB_CLASSIC_MAX_SPEED_RECORD)
        !           375:            return NO;
        !           376:        if (!isRead && rate > SB_CLASSIC_MAX_SPEED_PLAYBACK)
        !           377:            return NO;
        !           378:     }
        !           379:     
        !           380:     return YES;
        !           381: }
        !           382: 
        !           383: 
        !           384: - (BOOL) startDMAForChannel: (unsigned int) localChannel
        !           385:         read: (BOOL) isRead
        !           386:         buffer: (IOEISADMABuffer) buffer
        !           387:         bufferSizeForInterrupts: (unsigned int) bufferSize
        !           388: {
        !           389:     IOReturn ioReturn;
        !           390:     
        !           391: #ifdef DEBUG
        !           392:     IOLog("SoundBlaster8: startDMAForChannel\n");
        !           393: #endif DEBUG
        !           394: 
        !           395:     isValidRequest = [self isValidRequest:isRead];
        !           396:     
        !           397:     interruptTimedOut = NO;
        !           398:     
        !           399:     if (isValidRequest == NO)   {
        !           400:         IOLog("%s: unsupported %s mode.\n", [self name],
        !           401:                 isRead ? "recording" : "playback");
        !           402:        
        !           403:        if (isRead)
        !           404:            return YES;
        !           405:        else
        !           406:            return NO;
        !           407:     }
        !           408:         
        !           409:     if (isRead)
        !           410:         currentDMADirection = DMA_DIRECTION_IN;
        !           411:     else
        !           412:         currentDMADirection = DMA_DIRECTION_OUT;
        !           413: 
        !           414:     /*
        !           415:      * Output must be off while recording. 
        !           416:      */
        !           417:     if (![self isOutputMuted])
        !           418:        enableAudioOutput(isRead ? NO : YES);
        !           419: 
        !           420:     [self updateSampleRate];
        !           421:     
        !           422:     dmaDescriptorSize = bufferSize;    // used by interrupt handler
        !           423:             
        !           424: #ifdef DEBUG
        !           425:     if (lowSpeedDMA)
        !           426:         IOLog("SoundBlaster8: starting low speed DMA ");
        !           427:     else
        !           428:         IOLog("SoundBlaster8: starting high speed DMA ");
        !           429:         
        !           430:     if (isRead)
        !           431:         IOLog("input.\n");
        !           432:     else
        !           433:         IOLog("output.\n");
        !           434: #endif DEBUG
        !           435: 
        !           436:     ioReturn = [self startDMAForBuffer: buffer channel: localChannel];
        !           437: 
        !           438:     if (ioReturn != IO_R_SUCCESS) {
        !           439:         IOLog("%s: could not start DMA channel error %d\n",
        !           440:                 [self name], ioReturn);
        !           441:         return NO;
        !           442:     }
        !           443:         
        !           444:     ioReturn = [self enableChannel: localChannel];
        !           445:     
        !           446:     if (ioReturn != IO_R_SUCCESS) {
        !           447:         IOLog("%s: could not enable DMA channel error %d\n",
        !           448:                 [self name], ioReturn);
        !           449:         return NO;
        !           450:     }
        !           451: 
        !           452:     (void) [self enableAllInterrupts];
        !           453: 
        !           454:     /*
        !           455:      * The order is important here. See SB SDK page 12-8 and 12-13. 
        !           456:      */
        !           457:     if (lowSpeedDMA)    {
        !           458:         if (isRead) {
        !           459:             startDMA(DMA_DIRECTION_IN);
        !           460:         } else {
        !           461:             startDMA(DMA_DIRECTION_OUT);
        !           462:         }
        !           463:         [self setBufferCount: dmaDescriptorSize];
        !           464:     } else {
        !           465:         [self setBufferCount: dmaDescriptorSize];
        !           466:         if (isRead) {
        !           467:             startDMA(DMA_DIRECTION_IN);
        !           468:         } else {
        !           469:             startDMA(DMA_DIRECTION_OUT);
        !           470:         }
        !           471:     }
        !           472:     
        !           473:     return YES;
        !           474: }
        !           475: 
        !           476: - (void) stopDMAForChannel: (unsigned int) localChannel read: (BOOL) isRead
        !           477: {
        !           478: #ifdef DEBUG
        !           479:     IOLog("SoundBlaster8: stopDMAForChannel\n");
        !           480: #endif DEBUG
        !           481: 
        !           482:     /*
        !           483:      * DMA request was denied bacause of lack of hardware support. 
        !           484:      */
        !           485:     if (isValidRequest == NO)
        !           486:         return;
        !           487:     
        !           488:     if (isRead) {
        !           489:         stopDMAInput();
        !           490:     } else {
        !           491:         stopDMAOutput();
        !           492:     }
        !           493:     
        !           494:     (void)[self disableAllInterrupts];
        !           495:     
        !           496:     /*
        !           497:      * Disable channel only after disabling capture and playback. 
        !           498:      */
        !           499:     [self disableChannel: localChannel];
        !           500: 
        !           501:     if (isRead == NO)
        !           502:         enableAudioOutput(NO);
        !           503:        
        !           504:     /*
        !           505:      * Reset DSP to stop high speed DMA transfer. This is necessary since the
        !           506:      * current "DMA block" might be continuing in case the transfer was
        !           507:      * interrupted. 
        !           508:      */
        !           509:     if (lowSpeedDMA == NO) {
        !           510:        resetDSPQuick();
        !           511:     }
        !           512: }
        !           513: 
        !           514: static void clearInterrupts(void)
        !           515: {
        !           516:     /*
        !           517:      * Acknowledge and clear the interrupt.
        !           518:      */
        !           519: 
        !           520:     inb(sbDataAvailableStatusReg);
        !           521: }
        !           522: 
        !           523: - (IOAudioInterruptClearFunc) interruptClearFunc
        !           524: {
        !           525:     return clearInterrupts;
        !           526: }
        !           527: 
        !           528: - (void) interruptOccurredForInput: (BOOL *) serviceInput  
        !           529:                          forOutput: (BOOL *) serviceOutput
        !           530: {
        !           531: #ifdef DEBUG
        !           532:     IOLog("SoundBlaster8: handleHardwareInterrupt\n");
        !           533: #endif DEBUG
        !           534:     
        !           535:     /*
        !           536:      * Acknowledge and clear the interrupt.
        !           537:      */
        !           538: 
        !           539:     inb(sbDataAvailableStatusReg);
        !           540:     
        !           541:     /*
        !           542:      * We do not have simultaneous playback and record in SB.
        !           543:      */
        !           544:     if (currentDMADirection == DMA_DIRECTION_OUT)
        !           545:         *serviceOutput = YES;
        !           546:     else
        !           547:         *serviceInput = YES;
        !           548:         
        !           549:     if (lowSpeedDMA)    {
        !           550:         if (currentDMADirection == DMA_DIRECTION_IN) {
        !           551:             startDMA(DMA_DIRECTION_IN);
        !           552:         } else {
        !           553:             startDMA(DMA_DIRECTION_OUT);
        !           554:         }
        !           555:         [self setBufferCount: dmaDescriptorSize];      /* needed here */
        !           556:     } else {
        !           557:         //[self setBufferCount: dmaDescriptorSize];    /* but not here */
        !           558:         if (currentDMADirection == DMA_DIRECTION_IN) {
        !           559:             startDMA(DMA_DIRECTION_IN);
        !           560:         } else {
        !           561:             startDMA(DMA_DIRECTION_OUT);
        !           562:         }
        !           563:     }
        !           564: }
        !           565: 
        !           566: /*
        !           567:  * This routine will be called if interrupts are not being received. Some
        !           568:  * cards seem to lock up once in a while. 
        !           569:  */
        !           570: - (void) timeoutOccurred
        !           571: {
        !           572: #ifdef DEBUG
        !           573:     IOLog("%s: timeout occurred.\n", [self name]);
        !           574: #endif DEBUG
        !           575: 
        !           576:     if (interruptTimedOut == NO) {
        !           577:        resetDSPQuick();
        !           578:        interruptTimedOut = YES;                // reset only once
        !           579:     }
        !           580: }
        !           581: 
        !           582: /*
        !           583:  * Choose between different input sources.
        !           584:  */
        !           585:  
        !           586: - (void)setAnalogInputSource:(NXSoundParameterTag) val
        !           587: {
        !           588:     if (val == NX_SoundDeviceAnalogInputSource_Microphone) {
        !           589:         setInputLevel(MICROPHONE_LEVEL_INPUT);
        !           590:     } else if (val == NX_SoundDeviceAnalogInputSource_LineIn) {
        !           591:         setInputLevel(LINE_LEVEL_INPUT);
        !           592:     } else {
        !           593:         setInputLevel(MICROPHONE_LEVEL_INPUT);  // default
        !           594:     }
        !           595: }
        !           596: 
        !           597: /*
        !           598:  * Parameter access.
        !           599:  */
        !           600: 
        !           601: - (BOOL)acceptsContinuousSamplingRates
        !           602: {
        !           603:     return YES;
        !           604: }
        !           605: 
        !           606: - (void)getSamplingRatesLow:(int *)lowRate
        !           607:                                          high:(int *)highRate
        !           608: {
        !           609:     *lowRate = 4000;
        !           610:     *highRate = 44100;
        !           611: }
        !           612: 
        !           613: - (void)getSamplingRates:(int *)rates
        !           614:                                 count:(unsigned int *)numRates
        !           615: {
        !           616:     /* Return some supported rates */
        !           617:     rates[0] = 4000;
        !           618:     rates[1] = 8000;
        !           619:     rates[2] = 11025;
        !           620:     rates[3] = 22050;
        !           621:     rates[4] = 44100;
        !           622:     *numRates = 5;
        !           623: }
        !           624: 
        !           625: - (void)getDataEncodings: (NXSoundParameterTag *)encodings
        !           626:                                 count:(unsigned int *)numEncodings
        !           627: {
        !           628:     encodings[0] = NX_SoundStreamDataEncoding_Linear8;
        !           629:     *numEncodings = 1;
        !           630: }
        !           631: 
        !           632: - (unsigned int)channelCountLimit
        !           633: {
        !           634:     return (sbCardType.version == SB_PRO) ? 2 : 1;      /* stereo and mono */
        !           635: }
        !           636: 
        !           637: @end
        !           638: 

unix.superglobalmegacorp.com

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