예제 #1
0
IOReturn VoodooHDAEngine::convertInputSamples(const void *sampleBuf, void *destBuf,
		UInt32 firstSampleFrame, UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat,
		__unused IOAudioStream *audioStream)
{
	UInt32	numSamplesLeft, numSamples;
	Float32 	*floatDestBuf;
	
//    floatDestBuf = (float *)destBuf;
	UInt32 firstSample = firstSampleFrame * streamFormat->fNumChannels;
	numSamples = numSamplesLeft = numSampleFrames * streamFormat->fNumChannels;
	long int noiseMask = ~((1 << noiseLevel) - 1);
	
	UInt8 *sourceBuf = (UInt8 *) sampleBuf; 

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

		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:
					SInt8 *inputBuf8;
					
					inputBuf8 = &(((SInt8 *)sampleBuf)[firstSample]);
#if defined(__ppc__)
					Int8ToFloat32(inputBuf8, floatDestBuf, numSamplesLeft);
#elif defined(__i386__) || defined(__x86_64__)
					while (numSamplesLeft-- > 0) 
					{	
						*(floatDestBuf++) = (float)(*(inputBuf8++) &= (SInt8)noiseMask) * kOneOverMaxSInt8Value;
					}
#endif
					
					break;
				case 16:
				if (nativeEndianInts)
					if (vectorize) {
						NativeInt16ToFloat32((SInt16 *) &sampleBuf[2 * firstSample], floatDestBuf, numSamples);
					} else {
						SInt16 *inputBuf16;
						
						inputBuf16 = &(((SInt16 *)sampleBuf)[firstSample]);						
#if defined(__ppc__)
						SwapInt16ToFloat32(inputBuf16, floatDestBuf, numSamplesLeft, 16);
#elif defined(__i386__) || defined(__x86_64__)
						while (numSamplesLeft-- > 0) 
						{	
							*(floatDestBuf++) = (float)(*(inputBuf16++) &= (SInt16)noiseMask) * kOneOverMaxSInt16Value;
						}
#endif
					}

					
				else
					SwapInt16ToFloat32((SInt16 *) &sampleBuf[2 * firstSample], floatDestBuf, numSamples);
				break;

			case 20:
			case 24:
				if (nativeEndianInts)
					if (vectorize) {
						NativeInt24ToFloat32(&sourceBuf[3 * firstSample], floatDestBuf, numSamples);
					} else {
						register SInt8 *inputBuf24;
						
						// Multiply by 3 because 20 and 24 bit samples are packed into only three bytes, so we have to index bytes, not shorts or longs
						inputBuf24 = &(((SInt8 *)sampleBuf)[firstSample * 3]);
						
#if defined(__ppc__)
						SwapInt24ToFloat32((long *)inputBuf24, floatDestBuf, numSamplesLeft, 24);
#elif defined(__i386__) || defined(__x86_64__)
						register SInt32 inputSample;
						
						// [rdar://4311684] - Fixed 24-bit input convert routine. /thw
						while (numSamplesLeft-- > 1) 
						{	
							inputSample = (* (UInt32 *)inputBuf24) & 0x00FFFFFF & noiseMask;
							// Sign extend if necessary
							if (inputSample > 0x7FFFFF)
							{
								inputSample |= 0xFF000000;
							}
							inputBuf24 += 3;
							*(floatDestBuf++) = (float)inputSample * kOneOverMaxSInt24Value;
						}
						// Convert last sample. The following line does the same work as above without going over the edge of the buffer.
						inputSample = SInt32 ((UInt32 (*(UInt16 *) inputBuf24) & 0x0000FFFF & noiseMask)
											  | (SInt32 (*(inputBuf24 + 2)) << 16));
						*(floatDestBuf++) = (float)inputSample * kOneOverMaxSInt24Value;
#endif
						
					}

					
				else
					SwapInt24ToFloat32(&sourceBuf[3 * firstSample], floatDestBuf, numSamples);
				break;

			case 32:
				if (nativeEndianInts) {
					if (vectorize) {
						NativeInt32ToFloat32((SInt32 *) &sourceBuf[4 * firstSample], floatDestBuf, numSamples);
					} else {
						register SInt32 *inputBuf32;
						inputBuf32 = &(((SInt32 *)sampleBuf)[firstSample]);
						
#if defined(__ppc__)
						SwapInt32ToFloat32(inputBuf32, floatDestBuf, numSamplesLeft, 32);
#elif defined(__i386__) || defined(__x86_64__)
						while (numSamplesLeft-- > 0) {	
							*(floatDestBuf++) = (float)(*(inputBuf32++) & noiseMask) * kOneOverMaxSInt32Value;
						}
#endif
						
					}
				}
				else
					SwapInt32ToFloat32((SInt32 *) &sourceBuf[4 * firstSample], floatDestBuf, numSamples);
				break;

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

			}
			
			//Меняю местами значения для левого и правого канала
			if(mDevice && mDevice->mSwitchCh && (streamFormat->fNumChannels > 1)) {
				UInt32 i;
				Float32 tempSamples;
				
				for(i = 0; i < numSamples; i+= streamFormat->fNumChannels) {
					tempSamples = floatDestBuf[i];
					floatDestBuf[i] = floatDestBuf[i+1];
					floatDestBuf[i+1] = tempSamples;
				}
			}
			
		} 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(floatDestBuf, &((Float32 *) sampleBuf)[firstSample], numSamples * sizeof (Float32));
			} else
				errorMsg("convertInputSamples: 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(destBuf, &sourceBuf[offset], size);
	}

	return kIOReturnSuccess;
}
예제 #2
0
파일: ARClip.cpp 프로젝트: paulz/zirkonium
IOReturn AREngine::convertInputSamples(const void* inSourceBuffer, 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 linear PCM, which means the target is Float32 and we will be calling a blitter, which works in samples not frames
		Float32* theTargetBuffer = (Float32*)outTargetBuffer;
		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::convertInputSamples: can't handle signed integers with a bit width of 8 at the moment");
					}
					break;
				
				case 16:
					{
						SInt16* theSourceBuffer = (SInt16*)inSourceBuffer;
						if (nativeEndianInts)
							NativeInt16ToFloat32(mHasVectorUnit, &(theSourceBuffer[theFirstSample]), theTargetBuffer, theNumberSamples);
						else
							SwapInt16ToFloat32(mHasVectorUnit, &(theSourceBuffer[theFirstSample]), theTargetBuffer, theNumberSamples);
					}
					break;
				
				case 24:
					{
						UInt8* theSourceBuffer = (UInt8*)inSourceBuffer;
						if (nativeEndianInts)
							NativeInt24ToFloat32(mHasVectorUnit, &(theSourceBuffer[3*theFirstSample]), theTargetBuffer, theNumberSamples);
						else
							SwapInt24ToFloat32(mHasVectorUnit, &(theSourceBuffer[3*theFirstSample]), theTargetBuffer, theNumberSamples);
					}
					break;
				
				case 32:
					{
						SInt32* theSourceBuffer = (SInt32*)inSourceBuffer;
						if (nativeEndianInts)
							NativeInt32ToFloat32(mHasVectorUnit, &(theSourceBuffer[theFirstSample]), theTargetBuffer, theNumberSamples);
						else
							SwapInt32ToFloat32(mHasVectorUnit, &(theSourceBuffer[theFirstSample]), theTargetBuffer, theNumberSamples);
					}
					break;
				
				default:
					DebugMessageN1("AREngine::convertInputSamples: 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* theSourceBuffer = (Float32*)inSourceBuffer;
				memcpy(theTargetBuffer, &(theSourceBuffer[theFirstSample]), theNumberSamples * sizeof(Float32));
			}
			else
			{
				DebugMessageN2("AREngine::convertInputSamples: 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* theSourceBuffer = (SInt8*)inSourceBuffer;
		UInt32 theFirstByte = inFirstFrame * (inFormat->fBitWidth / 8) * inFormat->fNumChannels;
		UInt32 theNumberBytes = inNumberFrames * (inFormat->fBitWidth / 8) * inFormat->fNumChannels;
		memcpy(outTargetBuffer, &(theSourceBuffer[theFirstByte]), theNumberBytes);
	}

	return kIOReturnSuccess;
}