// 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 SMACscom::GetSourceData(SoundComponentData** outData) { ComponentResult theError = 0; UInt32 theNumberOutputPackets = 0; UInt32 theEncoderStatus = 0; UInt32 theActualOutputDataByteSize = 0; UInt32 maxPacketSize = 0; #if !TARGET_MAC_OS || !IS_COMPILER_WORKING float * tempFloatPtr; unsigned long tempULong = 0; float tempFloat; #endif *outData = NULL; // make sure we have some source data to start with if(SMACSCDUtility::NeedMoreSourceData(mSourceData)) { theError = SoundComponentGetSourceData(mSourceComponent, &mSourceData); ThrowIfError(theError, (CAException)theError, "SMACscom::GetSourceData: got an error from SoundComponentGetSourceData"); } // spin until we produce a packet of data or we run completely out of source data UInt32 theFramesProduced = 0; UInt32 theOutputDataByteSize = 0; while(SMACSCDUtility::HasData(mSourceData) && (theFramesProduced < mPacketFrameSize)) { // stuff as much input data into the encoder as we can UInt32 theInputDataByteSize = SMACSCDUtility::GetDataByteSize(mSourceData); UInt32 theNumberOfPackets = 0; maxPacketSize = min(kMaxInputSamples, theInputDataByteSize/sizeof(SInt16)); #if TARGET_MAC_OS && IS_COMPILER_WORKING NativeInt16ToFloat32( mHasAltiVec, ((short *)(mSourceData->buffer)), mFloatBuffer, maxPacketSize, 16); #else for (UInt32 i = 0; i < maxPacketSize; i++) { tempFloat = (float)(((short *)(mSourceData->buffer))[i]); tempFloatPtr = &tempFloat; if (tempFloat != 0.0 && tempFloat != -0.0) { tempULong = *((unsigned long *)tempFloatPtr); tempULong -= 0x07800000; tempFloatPtr = (float *)(&tempULong); } mFloatBuffer[i] = *tempFloatPtr; } #endif theInputDataByteSize = maxPacketSize * 4; // this is all we have converted //theInputDataByteSize *= 2; theError = AudioCodecAppendInputData(mEncoder, mFloatBuffer, &theInputDataByteSize, &theNumberOfPackets, NULL); ThrowIfError(theError, (CAException)theError, "SMACscom::GetSourceData: got an error from AudioCodecAppendInputData"); // update the source data with the amount of data consumed SMACSCDUtility::ConsumedData(mSourceData, theInputDataByteSize >> 1); // see if we can get a packet of output data theActualOutputDataByteSize = mMaxPacketByteSize; theNumberOutputPackets = 1; theEncoderStatus = kAudioCodecProduceOutputPacketFailure; theError = AudioCodecProduceOutputPackets(mEncoder, mOutputBuffer, &theActualOutputDataByteSize, &theNumberOutputPackets, NULL, &theEncoderStatus); ThrowIfError(theError, (CAException)theError, "SMACscom::GetSourceData: got an error from AudioCodecProduceOutputPackets"); if(theNumberOutputPackets == 1) { // we produced a full packet of frames, so we're done theFramesProduced = mPacketFrameSize; theOutputDataByteSize += theActualOutputDataByteSize; } else { // we didn't get the data, so get more input data if we have to if(SMACSCDUtility::NeedMoreSourceData(mSourceData)) { theError = SoundComponentGetSourceData(mSourceComponent, &mSourceData); ThrowIfError(theError, (CAException)theError, "SMACscom::GetSourceData: got an error from SoundComponentGetSourceData"); } } } if(theFramesProduced < mPacketFrameSize) { // Tell the encoder to pad with 0s -- this will change once the API is added if (mSourceIsExhausted) { UInt32 theInputDataByteSize = SMACSCDUtility::GetDataByteSize(mSourceData); // better be 0 UInt32 theNumberOfPackets = 0; maxPacketSize = min(kMaxInputSamples, theInputDataByteSize/sizeof(SInt16)); #if TARGET_MAC_OS && IS_COMPILER_WORKING NativeInt16ToFloat32( mHasAltiVec, ((short *)(mSourceData->buffer)), mFloatBuffer, maxPacketSize, 16); #else for (UInt32 i = 0; i < maxPacketSize; i++) { tempFloat = (float)(((short *)(mSourceData->buffer))[i]); tempFloatPtr = &tempFloat; if (tempFloat != 0.0 && tempFloat != -0.0) { tempULong = *((unsigned long *)tempFloatPtr); tempULong -= 0x07800000; tempFloatPtr = (float *)(&tempULong); } mFloatBuffer[i] = *tempFloatPtr; } #endif theInputDataByteSize = maxPacketSize * 4; // this is all we have converted //theInputDataByteSize *= 2; theError = AudioCodecAppendInputData(mEncoder, mFloatBuffer, &theInputDataByteSize, &theNumberOfPackets, NULL); ThrowIfError(theError, (CAException)theError, "SMACscom::GetSourceData: got an error from AudioCodecAppendInputData"); } // we ran out of input data, but we still haven't produced enough output data // so we have to try one last time to pull on the encoder in case it has // some left overs that it can give us theActualOutputDataByteSize = mMaxPacketByteSize; theNumberOutputPackets = 1; theEncoderStatus = kAudioCodecProduceOutputPacketFailure; theError = AudioCodecProduceOutputPackets(mEncoder, mOutputBuffer, &theActualOutputDataByteSize, &theNumberOutputPackets, NULL, &theEncoderStatus); ThrowIfError(theError, (CAException)theError, "SMACscom::GetSourceData: got an error from AudioCodecProduceOutputPackets"); if(theNumberOutputPackets == 1) { // we produced a full packet of frames, so we're done theFramesProduced = mPacketFrameSize; theOutputDataByteSize += theActualOutputDataByteSize; } } // set up the return values if any data was produced if(theFramesProduced > 0) { mOutputData.desc.buffer = mOutputBuffer; mOutputData.desc.sampleCount = theFramesProduced; mOutputData.bufferSize = theOutputDataByteSize; mOutputData.frameCount = 1; mOutputData.commonFrameSize = theOutputDataByteSize; mOutputData.desc.numChannels = mSourceData->numChannels; *outData = reinterpret_cast<SoundComponentData*>(&mOutputData); } }
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 }