void SMACscom::SetInfo(SoundSource inSourceID, OSType inSelector, void* inData) { switch(inSelector) { case siCompressionParams: { // process the the new params and produce an initialized // AudioCodec instance ComponentInstance theEncoder = SetCompressionParams(inData); ThrowIf(theEncoder == NULL, badFormat, "SMACscom::SetInfo: siCompressionParams didn't generate an encoder"); // get rid of the input data mSourceData = NULL; mOutputData.desc.sampleCount = 0; mOutputData.bufferSize = 0; mOutputData.frameCount = 0; mOutputData.commonFrameSize = 0; // close the old encoder if necessary if((mEncoder != NULL) && (theEncoder != mEncoder)) { CloseComponent(mEncoder); } // use the new one mEncoder = theEncoder; // get the number of frames in 1 packet of data UInt32 theSize = sizeof(UInt32); ComponentResult theError = AudioCodecGetProperty(mEncoder, kAudioCodecPropertyPacketFrameSize, &theSize, &mPacketFrameSize); ThrowIfError(theError, (CAException)theError, "SMACscom::SetInfo: siCompressionParams got an error from AudioCodecGetProperty while getting the packet frame size"); // get the maximum number of bytes in 1 packet of data theSize = sizeof(UInt32); theError = AudioCodecGetProperty(mEncoder, kAudioCodecPropertyMaximumPacketByteSize, &theSize, &mMaxPacketByteSize); ThrowIfError(theError, (CAException)theError, "SMACscom::SetInfo: siCompressionParams got an error from AudioCodecGetProperty while getting the maximum packet byte size"); // toss the old output buffer delete[] mOutputBuffer; // allocate enough space for 1 packet of data, since that's // that's all this component will produce per call to GetSourceData mOutputBuffer = new Byte[mMaxPacketByteSize]; } break; case siSourceIsExhausted: // in this case it seems to be passed by value -- ugh! mSourceIsExhausted = (Boolean)((UInt32)inData); // Now pass this on, so no break! default: ThrowIf(mSourceComponent == NULL, siUnknownInfoType, "SMACscom::SetInfo: no source to pass request to") ComponentResult theError = SoundComponentSetInfo(mSourceComponent, inSourceID, inSelector, inData); ThrowIfError(theError, (CAException)theError, "SMACscom::SetInfo: got an error from SoundComponentSetInfo"); break; }; }
ComponentInstance SMACIMAsdec::InitializeIMAAudioDecoder(Component inDecoderComponent, const AudioStreamBasicDescription& inFormat) { UInt32 theSize; ComponentInstance theDecoder = OpenComponent(inDecoderComponent); ThrowIf(theDecoder == NULL, badComponentInstance, "SMACIMAsdec::InitializeIMAAudioDecoder: couldn't open the component"); // first, give the decoder the info we have theSize = sizeof(AudioStreamBasicDescription); ComponentResult theError = AudioCodecSetProperty(theDecoder, kAudioCodecPropertyCurrentInputFormat, theSize, &inFormat); ThrowIfError(theError, (CAException)theError, "SMACIMAsdec::InitializeIMAAudioDecoder: got an error setting the input format"); // now find out what it can output theError = AudioCodecGetPropertyInfo(theDecoder, kAudioCodecPropertySupportedOutputFormats, &theSize, NULL); ThrowIfError(theError, (CAException)theError, "SMACIMAsdec::InitializeIMAAudioDecoder: got an error getting the available output format list size"); UInt32 theNumberAvailableOutputFormats = theSize / sizeof(AudioStreamBasicDescription); AudioStreamBasicDescription* theAvailableOutputFormats = new AudioStreamBasicDescription[theNumberAvailableOutputFormats]; try { theSize = theNumberAvailableOutputFormats * sizeof(AudioStreamBasicDescription); theError = AudioCodecGetProperty(theDecoder, kAudioCodecPropertySupportedOutputFormats, &theSize, theAvailableOutputFormats); ThrowIfError(theError, (CAException)theError, "SMACIMAsdec::InitializeIMAAudioDecoder: got an error getting the available output formats"); // find an acceptable output format AudioStreamBasicDescription* theOutputFormat = FindNEFloatFormat(theAvailableOutputFormats, theNumberAvailableOutputFormats); ThrowIf(theOutputFormat == NULL, badFormat, "SMACIMAsdec::InitializeIMAAudioDecoder: couldn't find an acceptable output format"); // finish filling out the output format theOutputFormat->mSampleRate = inFormat.mSampleRate; theOutputFormat->mChannelsPerFrame = inFormat.mChannelsPerFrame; theOutputFormat->mBytesPerFrame = 4 * inFormat.mChannelsPerFrame; theOutputFormat->mFormatID = kAudioFormatLinearPCM; theOutputFormat->mFormatFlags = kAudioFormatFlagsNativeFloatPacked; theOutputFormat->mBytesPerPacket = 4 * inFormat.mChannelsPerFrame; theOutputFormat->mFramesPerPacket = 1; theOutputFormat->mBitsPerChannel = 32; // tell the decoder about it theSize = sizeof(AudioStreamBasicDescription); theError = AudioCodecSetProperty(theDecoder, kAudioCodecPropertyCurrentOutputFormat, theSize, theOutputFormat); ThrowIfError(theError, (CAException)theError, "SMACIMAsdec::InitializeIMAAudioDecoder: got an error setting the output format"); delete[] theAvailableOutputFormats; theAvailableOutputFormats = NULL; } catch(...) { delete[] theAvailableOutputFormats; throw; } // finally initialize the decoder theError = AudioCodecInitialize(theDecoder, NULL, NULL, NULL, 0); ThrowIfError(theError, (CAException)theError, "SMACIMAsdec::InitializeIMAAudioDecoder: got an error initializing the decoder"); return theDecoder; }
void SMACsdec::SetInfo(SoundSource inSourceID, OSType inSelector, void* inData) { switch(inSelector) { case siDecompressionParams: { #if TARGET_API_MAC_OSX // Lock the thread if we can as we are going to completely replace the decoder bool threadLocked; threadLocked = mThreadStateMutex->Lock(); #endif // process the the new params and produce an initialized // AudioCodec instance ComponentInstance theDecoder = SetDecompressionParams(inData); ThrowIf(theDecoder == NULL, badFormat, "SMACsdec::SetInfo: siDecompressionParams didn't generate a decoder"); // get rid of the input data mSourceData = NULL; mOutputData.sampleCount = 0; // close the old decoder if necessary if((mDecoder != NULL) && (theDecoder != mDecoder)) { #if USE_DIRECT_ADEC DirectAudioCodecClose(mDecoder); #else CloseComponent(mDecoder); #endif } // use the new one mDecoder = theDecoder; // get the number of frames in 1 packet of data UInt32 theSize = sizeof(UInt32); ComponentResult theError = AudioCodecGetProperty(mDecoder, kAudioCodecPropertyPacketFrameSize, &theSize, &mPacketFrameSize); ThrowIfError(theError, (CAException)theError, "SMACsdec::SetInfo: siDecompressionParams got an error from AudioCodecGetProperty"); // toss the old output buffer delete[] mOutputBuffer; delete[] mFloatBuffer; // allocate enough space for 1 packet of data, since that's // that's all this component will produce per call to GetSourceData // note that this is going to be 16 bit integer mOutputBuffer = new Byte[mPacketFrameSize * 2 * mOutputData.numChannels]; mFloatBuffer = new float[mPacketFrameSize * mOutputData.numChannels]; #if TARGET_API_MAC_OSX // If we need to, unlock the thread if(threadLocked) { mThreadStateMutex->Unlock(); } #endif } break; default: ThrowIf(mSourceComponent == NULL, siUnknownInfoType, "SMACsdec::SetInfo: no source to pass request to") ComponentResult theError = SoundComponentSetInfo(mSourceComponent, inSourceID, inSelector, inData); throw theError; break; }; }