devsound/devsoundrefplugin/src/plugin/audio/MMFpcm16ToPcm16HwDevice.cpp
changeset 0 79dd3e2336a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/devsoundrefplugin/src/plugin/audio/MMFpcm16ToPcm16HwDevice.cpp	Fri Oct 08 19:40:43 2010 +0100
@@ -0,0 +1,281 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "MMFpcm16ToPcm16HwDevice.h"
+
+
+/**
+ *
+ *	Returns the created hw device for passing audio through audio.
+ *  for the wins implementation this would always be pcm16 although
+ *  this is effectively a null hw device that will pass any datatype through
+ *	@return	"CMMFPcm16ToPcm16HwDevice"
+ *
+ */
+CMMFPcm16ToPcm16HwDevice* CMMFPcm16ToPcm16HwDevice::NewL()
+	{
+    CMMFPcm16ToPcm16HwDevice* self = new (ELeave) CMMFPcm16ToPcm16HwDevice();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+ *
+ *	Second phase constructor.
+ *
+ */
+void CMMFPcm16ToPcm16HwDevice::ConstructL()
+	{
+    iCodec = new (ELeave) CMMFPcm16ToPcm16Codec();
+	static_cast<CMMFPcm16ToPcm16Codec*>(iCodec)->SetHwDevice(this);
+	}
+
+/**
+*
+* ~CMMFPcm16ToPcm16HwDevice
+*
+**/
+CMMFPcm16ToPcm16HwDevice::~CMMFPcm16ToPcm16HwDevice()
+	{
+	}
+
+/**
+*
+* Codec
+* @return CMMFSwCodec&
+**/
+CMMFSwCodec& CMMFPcm16ToPcm16HwDevice::Codec()
+	{
+	return *iCodec;
+	}
+
+
+
+
+
+/**
+*
+* ProcessL
+* @param aSrc Source Buffer
+* @param sDest Destintion Buffer
+* @return CMMFSwCodec::TCodecProcessResult
+*
+**/
+CMMFSwCodec::TCodecProcessResult CMMFPcm16ToPcm16Codec::ProcessL(const CMMFBuffer& /*aSource*/, CMMFBuffer& /*aDest*/)
+	{//no processing required for null codec
+	User::Leave(KErrNotSupported); 
+	//to keep compiler happy
+	TCodecProcessResult result;
+	result.iCodecProcessStatus = TCodecProcessResult::EEndOfData;
+	result.iSrcBytesProcessed = 0;
+	result.iDstBytesAdded = 0;
+	return result;
+	};
+
+
+TUint CMMFPcm16ToPcm16Codec::SourceBufferSize()
+	{
+	if (!iBufferSize) 
+		iBufferSize = iHwDevice->CalculateBufferSize();
+	return iBufferSize;
+	}
+
+
+TUint CMMFPcm16ToPcm16Codec::SinkBufferSize()
+	{
+	if (!iBufferSize) 
+		iBufferSize = iHwDevice->CalculateBufferSize();
+	return iBufferSize;
+	}
+
+void CMMFPcm16ToPcm16Codec::SetHwDevice(CMMFPcm16ToPcm16HwDevice* aHwDevice)
+	{
+	iHwDevice = aHwDevice;
+	}
+
+TUint CMMFPcm16ToPcm16HwDevice::CalculateBufferSize()
+	{
+	TUint sampleRate = 0;
+	TUint channels = 0;
+	TInt useBufferOfSize = 0;
+	TInt minBufferSize = 0;
+	TInt maxBufferSize = 0;
+
+	if (iPlayCustomInterface)
+		{
+		sampleRate = iSampleRate;
+		channels = iChannels;	
+		if ((sampleRate) && (channels))
+			{
+			RMdaDevSound::TSoundFormatsSupportedBuf playFormatsSupported;
+			if (iDataPath->Device().Handle())
+				{
+				iDataPath->Device().PlayFormatsSupported(playFormatsSupported);
+				minBufferSize = playFormatsSupported().iMinBufferSize;
+				maxBufferSize = playFormatsSupported().iMaxBufferSize;
+				}
+			else
+				{//try to get handle
+				TInt err = iDataPath->Device().Open();
+				if (err == KErrNone)
+					{
+					iDataPath->Device().PlayFormatsSupported(playFormatsSupported);
+					minBufferSize = playFormatsSupported().iMinBufferSize;
+					maxBufferSize = playFormatsSupported().iMaxBufferSize;
+					iDataPath->Device().Close();
+					}
+				}
+			}
+		}
+	if ((iRecordCustomInterface) && (!sampleRate) && (!channels))
+		{ //must be record
+		sampleRate = iSampleRate;
+		channels = iChannels;
+		if ((sampleRate) && (channels))
+			{//get max and min supported buffer sizes supported by hw
+			MSwSetParamInterface* interface = 
+				static_cast<MSwSetParamInterface*>(iDataPath->CustomInterface(KUidSwSetParamInterface));
+			if (interface)
+				{
+				interface->GetBufferSizes(minBufferSize, maxBufferSize);
+				}
+			}
+		}
+//	else convert so not applicable
+
+	if ((sampleRate) && (channels))
+		{
+		// Buffer size = (SampleRate * BytesPerSample * Channels) / 4
+		useBufferOfSize = ((sampleRate * 2 * channels)/KDevSoundFramesPerSecond + (KDevSoundDeltaFrameSize-1)) &~ (KDevSoundDeltaFrameSize-1);
+		//clamp buffer to desired limits
+		if(useBufferOfSize < KDevSoundMinFrameSize) 
+			useBufferOfSize = KDevSoundMinFrameSize;
+		else if(useBufferOfSize > KDevSoundMaxFrameSize) 
+			useBufferOfSize = KDevSoundMaxFrameSize;
+
+		//clamp buffer to limits of hardware
+		if (maxBufferSize)
+			{//buffer size limits have been set by sound driver
+			 //check we are within the limits
+			if(useBufferOfSize < minBufferSize)
+				useBufferOfSize = minBufferSize;
+			else if(useBufferOfSize > maxBufferSize)
+				useBufferOfSize = maxBufferSize;
+			}
+		}
+	else
+		{
+		useBufferOfSize = KPCM16ToPCM16BufferSize;
+		}
+
+	return useBufferOfSize;
+	}
+
+TAny* CMMFPcm16ToPcm16HwDevice::CustomInterface(TUid aInterfaceId)
+	{
+	// if this is the bitrate interface then
+	// we support this natively
+	if (aInterfaceId == KUidCustomInterfaceDevSoundBitRate)
+		{
+		return static_cast<MMMFDevSoundCustomInterfaceBitRate*> (this);
+		}
+	else
+		{
+		// otherwise pass the interface call onto the base class
+		return CMMFSwCodecWrapper::CustomInterface(aInterfaceId);
+		}
+	}
+
+void CMMFPcm16ToPcm16HwDevice::GetSupportedBitRatesL(RArray<TInt>& aSupportedBitRates)
+	{
+	// precondition of needing the datapath
+	if (!iDataPath)
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	// we only use this interface on the record interface
+	if (iRecordCustomInterface)
+		{
+		MSwInfoInterface* interface = 
+              static_cast<MSwInfoInterface*>(iDataPath->CustomInterface(KUidSwInfoInterface));
+        if (interface)
+              {
+              RArray<TInt> supportedSampleRates;
+              CleanupClosePushL(supportedSampleRates);
+              User::LeaveIfError(interface->GetSupportedSampleRates(supportedSampleRates));
+              BitRatesFromSampleRatesL(aSupportedBitRates, supportedSampleRates);
+              CleanupStack::PopAndDestroy(&supportedSampleRates);
+              }
+        else
+            {
+            User::Leave(KErrNotSupported);
+            }
+		}
+	}
+
+void CMMFPcm16ToPcm16HwDevice::BitRatesFromSampleRatesL(RArray<TInt>& aSupportedBitRates, 
+                                                        const RArray<TInt>& aSupportedSampleRates)
+    {
+    for (TInt index=0; index<aSupportedSampleRates.Count(); index++)
+        {
+        TInt sampleRate = aSupportedSampleRates[index];
+        TInt bitRate = sampleRate * iChannels * 16;
+        aSupportedBitRates.AppendL(bitRate);
+        }
+    }
+
+TInt CMMFPcm16ToPcm16HwDevice::BitRateL()
+	{
+	/*
+	inline void GetRecordFormat(TCurrentSoundFormatBuf& aFormat);
+	inline TInt SetRecordFormat(const TCurrentSoundFormatBuf& aFormat);
+	*/
+	TInt bitRate = 0;
+	
+	// need a number of channels and sample rate
+	if (!iSampleRate || !iChannels)
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	// should be able to just return sample rate * channels * 16 
+	if (iRecordCustomInterface)
+		{
+		bitRate = iSampleRate * iChannels * 16;	
+		}
+	return bitRate;
+	}
+
+void CMMFPcm16ToPcm16HwDevice::SetBitRateL(TInt aBitRate)
+	{
+	// need a datapath and number of channels
+	if (!iDataPath || (!iChannels))
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	// calculate the correct sample rate but don't set it yet
+	TInt sampleRate = aBitRate / 16 / iChannels;
+	
+	// if the datapath is not playing try and make change immediately
+	if (iDataPath->State() != CMMFSwCodecDataPath::EPlaying)
+		{
+		// update the member variable, assume it is picked up on next record.
+		iSampleRate = sampleRate;
+		}
+	}