Пример #1
0
// 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
			{
Пример #2
0
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);
	}
}
Пример #3
0
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
		}