Ejemplo n.º 1
0
IOReturn VoodooHDAEngine::clipOutputSamples(const void *mixBuf, void *sampleBuf, UInt32 firstSampleFrame,
		UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat,
		__unused IOAudioStream *audioStream)
{
	if(!streamFormat)
	{
        return kIOReturnBadArgument;
    }
	UInt32 firstSample = firstSampleFrame * streamFormat->fNumChannels;
	UInt32 numSamples = numSampleFrames * streamFormat->fNumChannels;
	Float32 *floatMixBuf = ((Float32*)mixBuf) + firstSample;
	
	UInt8 *sourceBuf = (UInt8 *) sampleBuf;

	// figure out what sort of blit we need to do
	if ((streamFormat->fSampleFormat == kIOAudioStreamSampleFormatLinearPCM) && streamFormat->fIsMixable) {
		// it's mixable linear PCM, which means we will be calling a blitter, which works in samples
		// not frames

		if (streamFormat->fNumericRepresentation == kIOAudioStreamNumericRepresentationSignedInt) {
			// it's some kind of signed integer, which we handle as some kind of even byte length
			bool nativeEndianInts;
			nativeEndianInts = (streamFormat->fByteOrder == kIOAudioStreamByteOrderLittleEndian);

			switch (streamFormat->fBitWidth) {
			case 8:
				if (nativeEndianInts)
				{
					SInt8* theOutputBufferSInt8 = ((SInt8*)sampleBuf) + firstSample;
					ClipFloat32ToSInt8_4(floatMixBuf, theOutputBufferSInt8, numSamples);
				} else
					Float32ToInt8(theMixBuffer, theOutputBufferSInt8, theNumberSamples);
					break;
					
			case 16:
				SInt16* theOutputBufferSInt16 = ((SInt16*)sampleBuf) + firstSample;
				if (nativeEndianInts) {
					if (vectorize) {
						Float32ToNativeInt16(floatMixBuf, theOutputBufferSInt16, numSamples);
					} else {
						ClipFloat32ToSInt16LE_4(floatMixBuf, theOutputBufferSInt16, numSamples);
					}
				}
				else
					Float32ToSwapInt16(floatMixBuf, (SInt16 *) &sourceBuf[2 * firstSample],
							numSamples);
				break;
					
			case 20:
			case 24:
				SInt32* theOutputBufferSInt24 = (SInt32*)(((UInt8*)sampleBuf) + (firstSample * 3));
				if (nativeEndianInts) {
					if (vectorize) {
						Float32ToNativeInt24(floatMixBuf, theOutputBufferSInt24, numSamples);
					} else {
						ClipFloat32ToSInt24LE_4(floatMixBuf, theOutputBufferSInt24, numSamples);						
					}
				}
				else
					Float32ToSwapInt24(floatMixBuf, &sourceBuf[3 * firstSample], numSamples);
				break;

			case 32:
				SInt32* theOutputBufferSInt32 = ((SInt32*)sampleBuf) + firstSample;
				if (nativeEndianInts) {
					if (vectorize) {
						Float32ToNativeInt32(floatMixBuf, theOutputBufferSInt32, numSamples);
					} else {					
						ClipFloat32ToSInt32LE_4(floatMixBuf, theOutputBufferSInt32, theNumberSamples);
					}
				}
				else
					Float32ToSwapInt32(floatMixBuf, (SInt32 *) &sourceBuf[4 * firstSample],
							numSamples);
				break;

			default:
				errorMsg("clipOutputSamples: can't handle signed integers with a bit width of %d",
						streamFormat->fBitWidth);
				break;

			}
		} else if (streamFormat->fNumericRepresentation == kIOAudioStreamNumericRepresentationIEEE754Float) {
			// it is some kind of floating point format
			if ((streamFormat->fBitWidth == 32) && (streamFormat->fBitDepth == 32) &&
					(streamFormat->fByteOrder == kIOAudioStreamByteOrderLittleEndian)) {
				// it's Float32, so we are just going to copy the data
				memcpy(&((Float32 *) sampleBuf)[firstSample], &floatMixBuf[firstSample],
						numSamples * sizeof (Float32));
			} else
				errorMsg("clipOutputSamples: can't handle floats with a bit width of %d, bit depth of %d, "
						"and/or the given byte order", streamFormat->fBitWidth, streamFormat->fBitDepth);
		}
	} else {
		// it's not linear PCM or it's not mixable, so just copy the data into the target buffer
		UInt32 offset = firstSampleFrame * (streamFormat->fBitWidth / 8) * streamFormat->fNumChannels;
		UInt32 size = numSampleFrames * (streamFormat->fBitWidth / 8) * streamFormat->fNumChannels;
		memcpy(&((SInt8 *) sampleBuf)[offset], &((SInt8 *) mixBuf)[offset], size);
	}

	return kIOReturnSuccess;
}
Ejemplo n.º 2
0
IOReturn AREngine::clipOutputSamples(const void* inMixBuffer, void* outTargetBuffer, UInt32 inFirstFrame, UInt32 inNumberFrames, const IOAudioStreamFormat* inFormat, IOAudioStream* /*inStream*/)
{
	//	figure out what sort of blit we need to do
	if((inFormat->fSampleFormat == kIOAudioStreamSampleFormatLinearPCM) && inFormat->fIsMixable)
	{
		//	it's mixable linear PCM, which means we will be calling a blitter, which works in samples not frames
		Float32* theMixBuffer = (Float32*)inMixBuffer;
		UInt32 theFirstSample = inFirstFrame * inFormat->fNumChannels;
		UInt32 theNumberSamples = inNumberFrames * inFormat->fNumChannels;
	
		if(inFormat->fNumericRepresentation == kIOAudioStreamNumericRepresentationSignedInt)
		{
			//	it's some kind of signed integer, which we handle as some kind of even byte length
			bool nativeEndianInts;
			#if TARGET_RT_BIG_ENDIAN
				nativeEndianInts = (inFormat->fByteOrder == kIOAudioStreamByteOrderBigEndian);
			#else
				nativeEndianInts = (inFormat->fByteOrder == kIOAudioStreamByteOrderLittleEndian);
			#endif
			
			switch(inFormat->fBitWidth)
			{
				case 8:
					{
						DebugMessage("AREngine::clipOutputSamples: can't handle signed integers with a bit width of 8 at the moment");
					}
					break;
				
				case 16:
					{
						SInt16* theTargetBuffer = (SInt16*)outTargetBuffer;
						if (nativeEndianInts)
							Float32ToNativeInt16(mHasVectorUnit, &(theMixBuffer[theFirstSample]), &(theTargetBuffer[theFirstSample]), theNumberSamples);
						else
							Float32ToSwapInt16(mHasVectorUnit, &(theMixBuffer[theFirstSample]), &(theTargetBuffer[theFirstSample]), theNumberSamples);
					}
					break;
				
				case 24:
					{
						UInt8* theTargetBuffer = (UInt8*)outTargetBuffer;
						if (nativeEndianInts)
							Float32ToNativeInt24(mHasVectorUnit, &(theMixBuffer[theFirstSample]), &(theTargetBuffer[3*theFirstSample]), theNumberSamples);
						else
							Float32ToSwapInt24(mHasVectorUnit, &(theMixBuffer[theFirstSample]), &(theTargetBuffer[3*theFirstSample]), theNumberSamples);
					}
					break;
				
				case 32:
					{
						SInt32* theTargetBuffer = (SInt32*)outTargetBuffer;
						if (nativeEndianInts)
							Float32ToNativeInt32(mHasVectorUnit, &(theMixBuffer[theFirstSample]), &(theTargetBuffer[theFirstSample]), theNumberSamples);
						else
							Float32ToSwapInt32(mHasVectorUnit, &(theMixBuffer[theFirstSample]), &(theTargetBuffer[theFirstSample]), theNumberSamples);
					}
					break;
				
				default:
					DebugMessageN1("AREngine::clipOutputSamples: can't handle signed integers with a bit width of %d", inFormat->fBitWidth);
					break;
				
			}
		}
		else if(inFormat->fNumericRepresentation == kIOAudioStreamNumericRepresentationIEEE754Float)
		{
			//	it is some kind of floating point format
		#if TARGET_RT_BIG_ENDIAN
			if((inFormat->fBitWidth == 32) && (inFormat->fBitDepth == 32) && (inFormat->fByteOrder == kIOAudioStreamByteOrderBigEndian))
		#else
			if((inFormat->fBitWidth == 32) && (inFormat->fBitDepth == 32) && (inFormat->fByteOrder == kIOAudioStreamByteOrderLittleEndian))
		#endif
			{
				//	it's Float32, so we are just going to copy the data
				Float32* theTargetBuffer = (Float32*)outTargetBuffer;
				memcpy(&(theTargetBuffer[theFirstSample]), &(theMixBuffer[theFirstSample]), theNumberSamples * sizeof(Float32));
			}
			else
			{
				DebugMessageN2("AREngine::clipOutputSamples: can't handle floats with a bit width of %d, bit depth of %d, and/or the given byte order", inFormat->fBitWidth, inFormat->fBitDepth);
			}
		}
	}
	else
	{
		//	it's not linear PCM or it's not mixable, so just copy the data into the target buffer
		SInt8* theMixBuffer = (SInt8*)inMixBuffer;
		SInt8* theTargetBuffer = (SInt8*)outTargetBuffer;
		UInt32 theFirstByte = inFirstFrame * (inFormat->fBitWidth / 8) * inFormat->fNumChannels;
		UInt32 theNumberBytes = inNumberFrames * (inFormat->fBitWidth / 8) * inFormat->fNumChannels;
		memcpy(&(theTargetBuffer[theFirstByte]), &(theMixBuffer[theFirstByte]), theNumberBytes);
	}

	return kIOReturnSuccess;
}