/*return value == 0 sucess == -1 fails */ static int open_output(void) { OSStatus err = 0; //no err UInt32 count, bufferSize; AudioDeviceID device = kAudioDeviceUnknown; AudioStreamBasicDescription format; // get the default output device for the HAL count = sizeof(globals.device); // it is required to pass the size of the data to be returned err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &count, (void *) &device); if (err != 0) goto Bail; // get the buffersize that the default device uses for IO count = sizeof(globals.deviceBufferSize); // it is required to pass the size of the data to be returned err = AudioDeviceGetProperty(device, 0, 0, kAudioDevicePropertyBufferSize, &count, &bufferSize); if (err != 0) goto Bail; if( globals.deviceBufferSize>BUFLEN ){ fprintf(stderr, "globals.deviceBufferSize NG: %ld\n", globals.deviceBufferSize); exit(1); } // get a description of the data format used by the default device count = sizeof(globals.deviceFormat); // it is required to pass the size of the data to be returned err = AudioDeviceGetProperty(device, 0, 0, kAudioDevicePropertyStreamFormat, &count, &format); if (err != 0) goto Bail; FailWithAction(format.mFormatID != kAudioFormatLinearPCM, err = -1, Bail); // bail if the format is not linear pcm // everything is ok so fill in these globals globals.device = device; globals.deviceBufferSize = bufferSize; globals.deviceFormat = format; init_variable(); err = AudioDeviceAddIOProc(globals.device, appIOProc, 0 ); // setup our device with an IO proc if (err != 0) goto Bail; globals.deviceFormat.mSampleRate = dpm.rate; #if 0 globals.deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; globals.deviceFormat.mBytesPerPacket = 4; globals.deviceFormat.mBytesPerFrame = 4; globals.deviceFormat.mBitsPerChannel = 0x10; err = AudioDeviceSetProperty(device, &inWhen, 0, 0, kAudioDevicePropertyStreamFormat, count, &globals.deviceFormat); if (err != 0) goto Bail; #endif #if 0 fprintf(stderr, "deviceBufferSize = %d\n", globals.deviceBufferSize); fprintf(stderr, "mSampleRate = %g\n", globals.deviceFormat.mSampleRate); fprintf(stderr, "mFormatID = 0x%08x\n", globals.deviceFormat.mFormatID); fprintf(stderr, "mFormatFlags = 0x%08x\n", globals.deviceFormat.mFormatFlags); fprintf(stderr, "mBytesPerPacket = 0x%08x\n", globals.deviceFormat.mBytesPerPacket); fprintf(stderr, "mBytesPerFrame = 0x%08x\n", globals.deviceFormat.mBytesPerFrame); fprintf(stderr, "mBitsPerChannel = 0x%08x\n", globals.deviceFormat.mBitsPerChannel); #endif Bail: return (err); }
// ---------------------------------------------------------------------------------------------------- bool PlatformInterfaceDBDMA_Mapped::init ( IOService* device, AppleOnboardAudio* provider, UInt32 inDBDMADeviceIndex ) { bool result = FALSE; IOService* theService; IORegistryEntry *macio; IORegistryEntry *gpio; IORegistryEntry *i2s; IORegistryEntry *i2sParent; IOMemoryMap *map; debugIOLog ( 3, "+ PlatformInterfaceDBDMA_Mapped::init ( %p, %p, %d )", device, provider, inDBDMADeviceIndex ); FailIf ( NULL == provider, Exit ); FailIf ( NULL == device, Exit ); result = super::init ( device, provider, inDBDMADeviceIndex ); if ( result ) { mKeyLargoService = IOService::waitForService ( IOService::serviceMatching ( "KeyLargo" ) ); debugIOLog ( 3, " sound's name is %s", ( (IORegistryEntry*)device)->getName () ); i2s = ( ( IORegistryEntry*)device)->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2s, result = false, Exit ); debugIOLog ( 3, " parent name is '%s'", i2s->getName () ); if ( 0 == strcmp ( "i2s-a", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell0; } else if ( 0 == strcmp ( "i2s-b", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell1; } else if ( 0 == strcmp ( "i2s-c", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell2; } else if ( 0 == strcmp ( "i2s-d", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell3; } else if ( 0 == strcmp ( "i2s-e", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell4; } else if ( 0 == strcmp ( "i2s-f", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell5; } else if ( 0 == strcmp ( "i2s-g", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell6; } else if ( 0 == strcmp ( "i2s-h", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell7; } debugIOLog ( 5, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber ); i2sParent = i2s->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2sParent, result = false, Exit ); debugIOLog ( 3, " parent name of '%s' is %s", i2s->getName (), i2sParent->getName () ); macio = i2sParent->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == macio, result = false, Exit ); debugIOLog ( 3, " macio name is %s", macio->getName () ); gpio = macio->childFromPath ( kGPIODTEntry, gIODTPlane); FailWithAction ( !gpio, result = false, Exit); debugIOLog ( 3, " gpio name is %s", gpio->getName () ); theService = ( OSDynamicCast ( IOService, i2s ) ); FailWithAction ( !theService, result = false, Exit ); map = theService->mapDeviceMemoryWithIndex ( inDBDMADeviceIndex ); FailWithAction ( 0 == map, result = false, Exit ); // cache the config space mSoundConfigSpace = (UInt8 *)map->getPhysicalAddress(); // sets the clock base address figuring out which I2S cell we're on if ((((UInt32)mSoundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S0BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S0BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell0; } else if ((((UInt32)mSoundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S1BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S1BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell1; } else { debugIOLog (3, " AudioI2SControl::init ERROR: unable to setup ioBaseAddress and i2SInterfaceNumber"); } FailIf (NULL == mIOBaseAddressMemory, Exit); // [3060321] ioConfigurationBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOConfigurationBaseAddress = (void *)mIOBaseAddressMemory->map()->getVirtualAddress(); FailIf ( NULL == mIOConfigurationBaseAddress, Exit ); // // There are three sections of memory mapped I/O that are directly accessed by the Apple02Audio. These // include the GPIOs, I2S DMA Channel Registers and I2S control registers. They fall within the memory map // as follows: // ~ ~ // |______________________________| // | | // | I2S Control | // |______________________________| <- soundConfigSpace = ioBase + i2s0BaseOffset ...OR... ioBase + i2s1BaseOffset // | | // ~ ~ // ~ ~ // |______________________________| // | | // | I2S DMA Channel | // |______________________________| <- i2sDMA = ioBase + i2s0_DMA ...OR... ioBase + i2s1_DMA // | | // ~ ~ // ~ ~ // |______________________________| // | FCRs | // | GPIO | <- gpio = ioBase + gpioOffsetAddress // | ExtIntGPIO | <- fcr = ioBase + fcrOffsetAddress // |______________________________| <- ioConfigurationBaseAddress // | | // ~ ~ // // The I2S DMA Channel is mapped in by the Apple02DBDMAAudioDMAEngine. Only the I2S control registers are // mapped in by the AudioI2SControl. The Apple I/O Configuration Space (i.e. FCRs, GPIOs and ExtIntGPIOs) // are mapped in by the subclass of Apple02Audio. The FCRs must also be mapped in by the AudioI2SControl // object as the init method must enable the I2S I/O Module for which the AudioI2SControl object is // being instantiated for. // // The physical addresses for memory mapped I/O within the KeyLargo system I/O controller are as follows: // // // // ______________________________ // /| | // / | | // / |______________________________| // ______________________________ / | | // | | | I2S 1 ('i2s-b') | // | | |______________________________|....0xnnn11000 [0x80011000] // | | | | // | | | I2S 0 ('i2s-a') | // | | |______________________________|....0xnnn10000 [0x80001000] // | Device Registers | / // | | / // | | / ______________________________ // | |/ /| | // |______________________________|__/ | | // | | |______________________________| // | | | | // | | | I2S 1 Rx DMA ('i2s-b') | // | | |______________________________|....0xnnn08300 [0x80008300] // | DMA Channel Registers | | | // | | | I2S 1 Tx DMA ('i2s-b') | // | | |______________________________|....0xnnn08200 [0x80008200] // | | | | // |______________________________| | I2S 0 Rx DMA ('i2s-a') | // | |\ |______________________________|....0xnnn08100 [0x80008100] // | | \ | | // | Reserved: read "0" | \ | I2S 0 Tx DMA ('i2s-a') | // | | \|______________________________|....0xnnn08000 [0x80008000] // |______________________________| // | | // | | // | Apple I/O Configuration | // | | // |______________________________|....0xnnn00000 [0x80011000] // // Map the I2S configuration registers mIOI2SBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace), kI2S_IO_CONFIGURATION_SIZE); FailIf ( NULL == mIOI2SBaseAddressMemory, Exit ); mI2SBaseAddress = (void *)mIOI2SBaseAddressMemory->map()->getVirtualAddress(); FailIf (NULL == mI2SBaseAddress, Exit); debugIOLog (3, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber); debugIOLog (3, " mIOI2SBaseAddressMemory = %p", mIOI2SBaseAddressMemory); debugIOLog (3, " mI2SBaseAddress = %p", mI2SBaseAddress); debugIOLog (3, " mIOBaseAddressMemory = %p", mIOBaseAddressMemory); debugIOLog (3, " mIOConfigurationBaseAddress = %p", mIOConfigurationBaseAddress); } Exit: debugIOLog ( 3, "- PlatformInterfaceDBDMA_Mapped::init ( %p, %p, %d ) returns %lX", device, provider, inDBDMADeviceIndex, result ); return result; }
void TLevelWriter3gp::saveSoundTrack(TSoundTrack *st) { Track theTrack; OSErr myErr = noErr; SoundDescriptionV1Handle mySampleDesc; Media myMedia; Handle myDestHandle; SoundComponentData sourceInfo; SoundComponentData destInfo; SoundConverter converter; CompressionInfo compressionInfo; int err; if (!st) throw TException("null reference to soundtrack"); if (st->getBitPerSample() != 16) { throw TImageException(m_path, "Only 16 bits per sample is supported"); } theTrack = NewMovieTrack(m_movie, 0, 0, kFullVolume); myErr = GetMoviesError(); if (myErr != noErr) throw TImageException(m_path, "error creating audio track"); FailIf(myErr != noErr, CompressErr); myDestHandle = NewHandle(0); FailWithAction(myDestHandle == NULL, myErr = MemError(), NoDest); *myDestHandle = (char *)st->getRawData(); ////////// // // create a media for the track passed in // ////////// // set new track to be a sound track m_soundDataRef = nil; m_hSoundMovieData = NewHandle(0); // Construct the Handle data reference err = PtrToHand(&m_hSoundMovieData, &m_soundDataRef, sizeof(Handle)); if ((err = GetMoviesError() != noErr)) throw TImageException(getFilePath(), "can't create Data Ref"); myMedia = NewTrackMedia(theTrack, SoundMediaType, st->getSampleRate(), m_soundDataRef, HandleDataHandlerSubType); //track->rate >> 16 myErr = GetMoviesError(); if (myErr != noErr) throw TImageException(m_path, "error setting audio track"); FailIf(myErr != noErr, Exit); // start a media editing session myErr = BeginMediaEdits(myMedia); if (myErr != noErr) throw TImageException(m_path, "error beginning edit audio track"); FailIf(myErr != noErr, Exit); sourceInfo.flags = 0x0; sourceInfo.format = kSoundNotCompressed; sourceInfo.numChannels = st->getChannelCount(); sourceInfo.sampleSize = st->getBitPerSample(); sourceInfo.sampleRate = st->getSampleRate(); sourceInfo.sampleCount = st->getSampleCount(); sourceInfo.buffer = (unsigned char *)st->getRawData(); sourceInfo.reserved = 0x0; destInfo.flags = kNoSampleRateConversion | kNoSampleSizeConversion | kNoSampleFormatConversion | kNoChannelConversion | kNoDecompression | kNoVolumeConversion | kNoRealtimeProcessing; destInfo.format = k16BitNativeEndianFormat; destInfo.numChannels = st->getChannelCount(); destInfo.sampleSize = st->getBitPerSample(); destInfo.sampleRate = st->getSampleRate(); destInfo.sampleCount = st->getSampleCount(); destInfo.buffer = (unsigned char *)st->getRawData(); destInfo.reserved = 0x0; SoundConverterOpen(&sourceInfo, &destInfo, &converter); myErr = SoundConverterGetInfo(converter, siCompressionFactor, &compressionInfo); if (myErr != noErr) throw TImageException(m_path, "error getting audio converter info"); myErr = GetCompressionInfo(fixedCompression, sourceInfo.format, sourceInfo.numChannels, sourceInfo.sampleSize, &compressionInfo); if (myErr != noErr) throw TImageException(m_path, "error getting audio compression info"); FailIf(myErr != noErr, ConverterErr); compressionInfo.bytesPerFrame = compressionInfo.bytesPerPacket * destInfo.numChannels; ////////// // // create a sound sample description // ////////// // use the SoundDescription format 1 because it adds fields for data size information // and is required by AddSoundDescriptionExtension if an extension is required for the compression format mySampleDesc = (SoundDescriptionV1Handle)NewHandleClear(sizeof(SoundDescriptionV1)); FailWithAction(myErr != noErr, myErr = MemError(), Exit); (**mySampleDesc).desc.descSize = sizeof(SoundDescriptionV1); (**mySampleDesc).desc.dataFormat = destInfo.format; (**mySampleDesc).desc.resvd1 = 0; (**mySampleDesc).desc.resvd2 = 0; (**mySampleDesc).desc.dataRefIndex = 1; (**mySampleDesc).desc.version = 1; (**mySampleDesc).desc.revlevel = 0; (**mySampleDesc).desc.vendor = 0; (**mySampleDesc).desc.numChannels = destInfo.numChannels; (**mySampleDesc).desc.sampleSize = destInfo.sampleSize; (**mySampleDesc).desc.compressionID = 0; (**mySampleDesc).desc.packetSize = 0; (**mySampleDesc).desc.sampleRate = st->getSampleRate() << 16; (**mySampleDesc).samplesPerPacket = compressionInfo.samplesPerPacket; (**mySampleDesc).bytesPerPacket = compressionInfo.bytesPerPacket; (**mySampleDesc).bytesPerFrame = compressionInfo.bytesPerFrame; (**mySampleDesc).bytesPerSample = compressionInfo.bytesPerSample; ////////// // // add samples to the media // ////////// myErr = AddMediaSample(myMedia, myDestHandle, 0, destInfo.sampleCount * compressionInfo.bytesPerFrame, 1, (SampleDescriptionHandle)mySampleDesc, destInfo.sampleCount * compressionInfo.samplesPerPacket, 0, NULL); if (myErr != noErr) throw TImageException(m_path, "error adding audio samples"); FailIf(myErr != noErr, MediaErr); myErr = EndMediaEdits(myMedia); if (myErr != noErr) throw TImageException(m_path, "error ending audio edit"); FailIf(myErr != noErr, MediaErr); ////////// // // insert the media into the track // ////////// myErr = InsertMediaIntoTrack(theTrack, 0, 0, GetMediaDuration(myMedia), fixed1); if (myErr != noErr) throw TImageException(m_path, "error inserting audio track"); FailIf(myErr != noErr, MediaErr); goto Done; ConverterErr: NoDest: CompressErr: Exit: Done: MediaErr: if (mySampleDesc != NULL) DisposeHandle((Handle)mySampleDesc); if (converter) SoundConverterClose(converter); if (myErr != noErr) throw TImageException(m_path, "error saving audio track"); }