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