// Overrides the method in SMACsdec. Necessary due to the way IMA works. This will not be necessary // for many codecs. void SMACIMAsdec::GetSourceData(SoundComponentData** outData) { // initialize the return value *outData = NULL; // stuff as many packets as we can into the decoder UInt32 theError = 0; void* theInputData = NULL; UInt32 theInputDataByteSize = 0; UInt32 theInputDataFrameSize = 0; #if TARGET_API_MAC_OSX bool threadLocked; #endif #if !(TARGET_MAC_OS && IS_COMPILER_WORKING) UInt32 totalFloats; #endif #if TARGET_API_MAC_OSX // Lock the thread. The last thing we want is to have our state change in the middle of // a decode -- it will typically cause a crash threadLocked = mThreadStateGuard->Lock(); #endif // prime things with the current packet GetCurrentInputPacket(theInputData, theInputDataByteSize, theInputDataFrameSize); // Trying to mimic Decompressor.c in this case if((theInputData == NULL) || (theInputDataFrameSize == 0 && theInputDataByteSize == 0) ) { // silence with non-zero duration. mOutputData.buffer = NULL; *outData = mSourceData; } else { // On more complex decoders this isn't always necessary if (!mDecoder) { mNumChannels = mOutputData.numChannels = mSourceData->numChannels; mSampleRate = (mSourceData->sampleRate) >> 16; CreateIMADecoder(); } // loop and stuff the decoder with packets bool isDone = false; while((theInputData != NULL) && (theInputDataByteSize != 0) && (!isDone)) { // give the current packet to the decoder UInt32 theNumberInputPackets = 1; UInt32 theNumberInputBytesConsumed = theInputDataByteSize; AudioStreamPacketDescription theInputPacketDescription = { 0, 0, theInputDataByteSize }; theError = AudioCodecAppendInputData(mDecoder, theInputData, &theNumberInputBytesConsumed, &theNumberInputPackets, &theInputPacketDescription); ThrowIfError(theError, (CAException)theError, "SMACIMAsdec::GetSourceData: got an error from AudioCodecAppendInputData"); // we know that the decoder is full if it ever says that it didn't take any data from the input buffer if(theNumberInputBytesConsumed > 0 && theNumberInputBytesConsumed == theInputDataByteSize) { // consume the data the decoder used ConsumeCurrentInputPacket(theInputDataByteSize, 0); // get the next packet GetCurrentInputPacket(theInputData, theInputDataByteSize, theInputDataFrameSize); } else if (theNumberInputBytesConsumed > 0) { ConsumeCurrentInputPacket(theNumberInputBytesConsumed, 0); isDone = true; } else { isDone = true; } } // the decoder is as full of data as we can make it at this time, // so pull out 1 packet of output data UInt32 theOutputDataByteSize = mPacketFrameSize * sizeof(float) * mOutputData.numChannels; UInt32 theNumberOutputFrames = mPacketFrameSize; UInt32 theDecoderStatus = kAudioCodecProduceOutputPacketFailure; theError = AudioCodecProduceOutputPackets(mDecoder, mFloatBuffer, &theOutputDataByteSize, &theNumberOutputFrames, NULL, &theDecoderStatus); ThrowIfError(theError, (CAException)theError, "SMACIMAsdec::GetSourceData: got an error from AudioCodecProduceOutputPackets"); // set up the return values if we got a packet back from the decoder if(theNumberOutputFrames) { // gcc 2.95 doesn't work right in this case, so we guard against it #if TARGET_MAC_OS && IS_COMPILER_WORKING Float32ToNativeInt16(mHasAltiVec, mFloatBuffer, ((short *)mOutputBuffer), theOutputDataByteSize >> 2); #else totalFloats = theOutputDataByteSize >> 2; for (unsigned int i = 0; i < totalFloats; i++) { ((short *)mOutputBuffer)[i] = (SInt16)(32768.0 * mFloatBuffer[i]); } #endif mOutputData.buffer = mOutputBuffer; if (mOutputData.numChannels == 2) // It's either 1 or 2 here in SMAC land { mOutputData.sampleCount = (theOutputDataByteSize >> 3); // Yes, these really are frames. } else {
void SMACsdec::GetSourceData(SoundComponentData** outData) { // initialize the return value *outData = NULL; // stuff as many packets as we can into the decoder UInt32 theError = 0; void* theInputData = NULL; UInt32 theInputDataByteSize = 0; UInt32 theInputDataFrameSize = 0; #if TARGET_API_MAC_OSX bool threadLocked; #endif #if !(TARGET_MAC_OS && IS_COMPILER_WORKING) UInt32 totalFloats; #endif #if TARGET_API_MAC_OSX // Lock the thread. The last thing we want is to have our state change in the middle of // a decode -- it will typically cause a crash threadLocked = mThreadStateMutex->Lock(); #endif // prime things with the current packet GetCurrentInputPacket(theInputData, theInputDataByteSize, theInputDataFrameSize); // Trying to mimic Decompressor.c in this case if((theInputData == NULL) || (theInputDataFrameSize == 0 && theInputDataByteSize == 0) ) { // silence with non-zero duration. mOutputData.buffer = NULL; *outData = mSourceData; } else { // loop and stuff the decoder with packets bool isDone = false; while((theInputData != NULL) && (theInputDataByteSize != 0) && (!isDone)) { // give the current packet to the decoder UInt32 theNumberInputPackets = 1; UInt32 theNumberInputBytesConsumed = theInputDataByteSize; AudioStreamPacketDescription theInputPacketDescription = { 0, 0, theInputDataByteSize }; theError = AudioCodecAppendInputData(mDecoder, theInputData, &theNumberInputBytesConsumed, &theNumberInputPackets, &theInputPacketDescription); //printf("mDecoder == %lu, Appended %ld bytes in %ld packets\n", (UInt32)(&mDecoder), theNumberInputBytesConsumed, theNumberInputPackets); ThrowIfError(theError, (CAException)theError, "SMACsdec::GetSourceData: got an error from AudioCodecAppendInputData"); // we know that the decoder is full if it ever says that it didn't take any data from the input buffer if( (theNumberInputBytesConsumed > 0) && (theNumberInputBytesConsumed == theInputDataByteSize) ) { // consume the data the decoder used ConsumeCurrentInputPacket(theInputDataByteSize, 0); // get the next packet GetCurrentInputPacket(theInputData, theInputDataByteSize, theInputDataFrameSize); } else if (theNumberInputBytesConsumed > 0) { ConsumeCurrentInputPacket(theNumberInputBytesConsumed, 0); isDone = true; } else { isDone = true; } } // the decoder is as full of data as we can make it at this time, // so pull out 1 packet of output data UInt32 theOutputDataByteSize = mPacketFrameSize * sizeof(float) * mOutputData.numChannels; UInt32 theNumberOutputFrames = mPacketFrameSize; UInt32 theDecoderStatus = kAudioCodecProduceOutputPacketFailure; theError = AudioCodecProduceOutputPackets(mDecoder, mFloatBuffer, &theOutputDataByteSize, &theNumberOutputFrames, NULL, &theDecoderStatus); //printf (" theNumberOutputFrames == %ld\n",theNumberOutputFrames); ThrowIfError(theError, (CAException)theError, "SMACsdec::GetSourceData: got an error from AudioCodecProduceOutputPackets"); // set up the return values if we got a packet back from the decoder if(theNumberOutputFrames) { //theNumberOutputFrames = theOutputDataByteSize / mOutputData.numChannels / sizeof(float); // ThrowIfError(theNumberOutputFrames != theOutputDataByteSize / mOutputData.numChannels / sizeof(float), "SMACsdec::GetSourceData: got an error from AudioCodecProduceOutputPackets"); #if TARGET_MAC_OS && IS_COMPILER_WORKING Float32ToNativeInt16(mHasAltiVec, mFloatBuffer, ((short *)mOutputBuffer), theOutputDataByteSize >> 2); #else totalFloats = theOutputDataByteSize >> 2; for (unsigned int i = 0; i < totalFloats; i++) { ((short *)mOutputBuffer)[i] = (SInt16)(32768.0 * mFloatBuffer[i]); } #endif mOutputData.buffer = mOutputBuffer; if (mOutputData.numChannels == 2) // It's either 1 or 2 here in SMAC land { mOutputData.sampleCount = (theOutputDataByteSize >> 3); // These really are frames. It's a QuickTime/SoundManager ism } else { mOutputData.sampleCount = (theOutputDataByteSize >> 2); } *outData = &mOutputData; #if CaptureDataToFile if(mOutputFileRefNum != -1) { UInt32 theActualBytesWritten = 0; FSWriteFork(mOutputFileRefNum, fsAtMark, 0, theOutputDataByteSize, mOutputBuffer, &theActualBytesWritten); } #endif }