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; }
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; }