bool ARDevice::CreateAudioEngine() { // initialize some locals AREngine* theEngine = NULL; // set the return value bool theAnswer = true; // get the description of th engine to build OSDictionary* theEngineDictionary = OSDynamicCast(OSDictionary, getProperty(AUDIO_ENGINE_KEY)); FailIfNULLWithAction(theEngineDictionary, theAnswer = false, Done, "ARDevice::CreateAudioEngines: couldn't get the engine description"); // create the engine theEngine = new AREngine; if(theEngine != NULL) { // initialize the engine if(theEngine->init(theEngineDictionary)) { // activate the new engine, if initialization was successful activateAudioEngine(theEngine); } // release the engine theEngine->release(); } Done: return theAnswer; }
bool AREngine::CreateStreams(IOAudioSampleRate* outInitialSampleRate, UInt32* outNumberChannels) { // set the return values bool theAnswer = true; *outNumberChannels = 0; // set up some local variables OSArray* theFormatArray = NULL; OSArray* theSampleRateArray = NULL; OSString* theOSString = NULL; UInt32 theNumberStreams = NUM_STREAMS; OSNumber* theOSNumber = NULL; // get the array of formats theFormatArray = OSDynamicCast(OSArray, getProperty(FORMATS_KEY)); FailIfNULLWithAction(theFormatArray, theAnswer = false, Done, "AREngine::CreateStreams: Couldn't get the format array"); // get the array of sample rates theSampleRateArray = OSDynamicCast(OSArray, getProperty(SAMPLE_RATES_KEY)); FailIfNULLWithAction(theSampleRateArray, theAnswer = false, Done, "AREngine::CreateStreams: Couldn't get the sample rate array"); // get the description theOSString = OSDynamicCast(OSString, getProperty(DESCRIPTION_KEY)); if(theOSString != NULL) { setDescription(theOSString->getCStringNoCopy()); } // get the number of streams theOSNumber = OSDynamicCast(OSNumber, getProperty(NUM_STREAMS_KEY)); if(theOSNumber != NULL) { theNumberStreams = theOSNumber->unsigned32BitValue(); } // make the streams for(UInt32 theStreamNumber = 0; theStreamNumber < theNumberStreams; ++theStreamNumber) { // initialize some local variables bool theResult = false; UInt32 theMaxBitWidth = 0; UInt32 theMaxNumberChannels = 0; IOAudioStream* theInputStream = NULL; IOAudioStream* theOutputStream = NULL; OSCollectionIterator* theFormatIterator = NULL; OSCollectionIterator* theSampleRateIterator = NULL; OSDictionary* theFormatDictionary = NULL; IOAudioSampleRate theSampleRate = { 0, 0 }; IOAudioStreamFormat theInitialFormat; bool theInitialFormatSet = false; char theInputStreamName[32]; char theOutputStreamName[32]; UInt32 theStreamBufferSize = 0; // allocate and initialize the input stream if(theNumberStreams > 1) { snprintf(theInputStreamName, 32, "Input Stream #%ld", theStreamNumber + 1); } else { snprintf(theInputStreamName, 32, "Input Stream"); } theInputStream = new IOAudioStream; FailIfNULLWithAction(theInputStream, theAnswer = false, Error, "AREngine::CreateStreams: couldn't create the input stream"); theResult = theInputStream->initWithAudioEngine(this, kIOAudioStreamDirectionInput, *outNumberChannels + 1, theInputStreamName); FailIfWithAction(!theResult, theAnswer = false, Error, "AREngine::CreateStreams: couldn't initialize the input stream"); // allocate and initialize the output stream if(theNumberStreams > 1) { snprintf(theOutputStreamName, 32, "Output Stream #%ld", theStreamNumber + 1); } else { snprintf(theOutputStreamName, 32, "Output Stream"); } theOutputStream = new IOAudioStream; FailIfNULLWithAction(theOutputStream, theAnswer = false, Error, "AREngine::CreateStreams: couldn't create the output stream"); theResult = theOutputStream->initWithAudioEngine(this, kIOAudioStreamDirectionOutput, *outNumberChannels + 1, theOutputStreamName); FailIfWithAction(!theResult, theAnswer = false, Error, "AREngine::CreateStreams: couldn't initialize the output stream"); // make an iterator for the format array theFormatIterator = OSCollectionIterator::withCollection(theFormatArray); FailIfNULLWithAction(theFormatIterator, theAnswer = false, Error, "AREngine::CreateStreams: couldn't create the format iterator"); // make an iterator for the sample rate array theSampleRateIterator = OSCollectionIterator::withCollection(theSampleRateArray); FailIfNULLWithAction(theSampleRateIterator, theAnswer = false, Error, "AREngine::CreateStreams: couldn't create the sample rate iterator"); // iterate through the formats theFormatIterator->reset(); theFormatDictionary = (OSDictionary*)theFormatIterator->getNextObject(); while(theFormatDictionary != NULL) { // make sure we have a dictionary if(OSDynamicCast(OSDictionary, theFormatDictionary) != NULL) { // convert the dictionary into something we can deal with IOAudioStreamFormat theFormat; FailIfNULLWithAction(IOAudioStream::createFormatFromDictionary(theFormatDictionary, &theFormat), theAnswer = false, Error, "AREngine::CreateStreams: couldn't make a format out of the dictionary"); // make sure the initial format is set if(!theInitialFormatSet) { theInitialFormat = theFormat; } // iterate through the sample rates theSampleRateIterator->reset(); theOSNumber = (OSNumber*)theSampleRateIterator->getNextObject(); while(theOSNumber != NULL) { // make sure we have a number if(OSDynamicCast(OSNumber, theOSNumber) != NULL) { // get the sample rate theSampleRate.whole = theOSNumber->unsigned32BitValue(); // make sure the initial sample rate is set if(outInitialSampleRate->whole == 0) { outInitialSampleRate->whole = theSampleRate.whole; } // add the format to the input stream theInputStream->addAvailableFormat(&theFormat, &theSampleRate, &theSampleRate); // add the format to the output stream theOutputStream->addAvailableFormat(&theFormat, &theSampleRate, &theSampleRate); // track a few things theMaxNumberChannels = (theFormat.fNumChannels > theMaxNumberChannels) ? theFormat.fNumChannels : theMaxNumberChannels; theMaxBitWidth = (theFormat.fBitWidth > theMaxBitWidth) ? theFormat.fBitWidth : theMaxBitWidth; } // go to the next sample rate theOSNumber = (OSNumber*)theSampleRateIterator->getNextObject(); } } // go to the next format theFormatDictionary = (OSDictionary*)theFormatIterator->getNextObject(); } // calculate the size of the stream buffer theStreamBufferSize = mBlockSize * mNumberBlocks * theMaxNumberChannels * theMaxBitWidth / 8; // allocate the buffers if necessary if(mOutputBuffer == NULL) { // calculate the size mOutputBufferSize = theStreamBufferSize * theNumberStreams; // allocate the output buffer mOutputBuffer = (void*)IOMallocAligned(mOutputBufferSize, PAGE_SIZE); FailIfNULLWithAction(mOutputBuffer, theAnswer = false, Error, "AREngine::CreateStreams: couldn't allocate the output buffer"); // the input size is the same as the output size mInputBufferSize = mOutputBufferSize; // allocate the input buffer mInputBuffer = mOutputBuffer; } // set some info about the stream theInputStream->setTerminalType(INPUT_UNDEFINED); theOutputStream->setTerminalType(OUTPUT_UNDEFINED); // set the initial stream formats theInputStream->setFormat(&theInitialFormat, false); theOutputStream->setFormat(&theInitialFormat, false); // set the data buffer for the streams theInputStream->setSampleBuffer(&((UInt8*)mInputBuffer)[theStreamBufferSize * theStreamNumber], theStreamBufferSize); theOutputStream->setSampleBuffer(&((UInt8*)mOutputBuffer)[theStreamBufferSize * theStreamNumber], theStreamBufferSize); // add the streams to the engine addAudioStream(theInputStream); theInputStream->release(); theInputStream = NULL; addAudioStream(theOutputStream); theOutputStream->release(); theOutputStream = NULL; theFormatIterator->release(); theFormatIterator = NULL; theSampleRateIterator->release(); theSampleRateIterator = NULL; *outNumberChannels += theMaxNumberChannels; continue; Error: if(theInputStream) { theInputStream->release(); } if(theOutputStream) { theOutputStream->release(); } if(theFormatIterator) { theFormatIterator->release(); } if(theSampleRateIterator) { theSampleRateIterator->release(); } goto Done; } Done: return theAnswer; }