sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "MmfUtilities.h" sl@0: #include "mmfutilitiespriv.h" sl@0: #include "mmf/utils/rateconvert.h" sl@0: sl@0: const TInt KMaxInt16Bit = 65536 ; //Maximum for a 16bit int sl@0: sl@0: EXPORT_C CMMFChannelAndSampleRateConverterFactory::~CMMFChannelAndSampleRateConverterFactory() sl@0: { sl@0: delete iConverter; sl@0: } sl@0: sl@0: sl@0: EXPORT_C CMMFChannelAndSampleRateConverter* CMMFChannelAndSampleRateConverterFactory::CreateConverterL(TInt aFromRate,TInt aFromChannels, sl@0: TInt aToRate,TInt aToChannels) sl@0: { sl@0: if(aFromRate<0 || aFromChannels<0 || aToRate<0 || aToChannels<0) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: sl@0: iFromRate=aFromRate; sl@0: iToRate=aToRate; sl@0: iFromChannels=aFromChannels; sl@0: iToChannels=aToChannels; sl@0: return CreateConverterL(); sl@0: } sl@0: sl@0: EXPORT_C CMMFChannelAndSampleRateConverter* CMMFChannelAndSampleRateConverterFactory::CreateConverterL() sl@0: { sl@0: if (iConverter sl@0: &&(iFromRate==iConverter->iFromRate) sl@0: &&(iToRate==iConverter->iToRate) sl@0: &&(iFromChannels==iConverter->iFromChannels) sl@0: &&(iToChannels==iConverter->iToChannels)) sl@0: return iConverter; sl@0: sl@0: delete iConverter; sl@0: iConverter=NULL; sl@0: sl@0: iConverter = CMMFForwardingChannelAndSampleRateConverter::NewL(iFromRate, iFromChannels, iToRate, iToChannels); sl@0: sl@0: return iConverter; sl@0: } sl@0: sl@0: // SetRates kept for BC reasons - populates publically visible properties sl@0: sl@0: void CMMFChannelAndSampleRateConverter::SetRates(TInt aFromRate,TInt aFromChannels, sl@0: TInt aToRate,TInt aToChannels) sl@0: { sl@0: iFromRate=aFromRate; sl@0: iToRate=aToRate; sl@0: iFromChannels=aFromChannels; sl@0: iToChannels=aToChannels; sl@0: sl@0: iRatio = (TReal)aFromRate / (TReal)aToRate; sl@0: sl@0: TInt quotient = (TInt)iRatio; sl@0: TReal remainder = iRatio - (TReal)quotient; sl@0: iFraction = quotient * KMaxInt16Bit + (TInt32)(remainder * KMaxInt16Bit); sl@0: sl@0: Reset(); sl@0: } sl@0: sl@0: // sl@0: // Forwarding converter - adapt to the implementation in audioutils. sl@0: // sl@0: sl@0: CMMFForwardingChannelAndSampleRateConverter* CMMFForwardingChannelAndSampleRateConverter::NewL(TInt aFromRate, sl@0: TInt aFromChannels, sl@0: TInt aToRate, sl@0: TInt aToChannels) sl@0: { sl@0: CMMFForwardingChannelAndSampleRateConverter* self = new (ELeave) CMMFForwardingChannelAndSampleRateConverter; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aFromRate,aFromChannels,aToRate,aToChannels); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CMMFForwardingChannelAndSampleRateConverter::CMMFForwardingChannelAndSampleRateConverter() sl@0: { sl@0: } sl@0: sl@0: void CMMFForwardingChannelAndSampleRateConverter::ConstructL(TInt aFromRate, sl@0: TInt aFromChannels, sl@0: TInt aToRate, sl@0: TInt aToChannels) sl@0: { sl@0: SetRates(aFromRate, aFromChannels, aToRate, aToChannels); sl@0: // delib called before iRealConverter created. Reset() will be no-op. sl@0: // this is preserved solely to keep BC with original API that exposes too much sl@0: iRealConverter = CChannelAndSampleRateConverter::CreateL(aFromRate,aFromChannels,aToRate,aToChannels); sl@0: } sl@0: sl@0: CMMFForwardingChannelAndSampleRateConverter::~CMMFForwardingChannelAndSampleRateConverter() sl@0: { sl@0: delete iRealConverter; sl@0: } sl@0: sl@0: TInt CMMFForwardingChannelAndSampleRateConverter::Convert(const CMMFDataBuffer& aSrcBuffer, CMMFDataBuffer& aDstBuffer) sl@0: { sl@0: TInt ignore = iRealConverter->Convert(aSrcBuffer.Data(), aDstBuffer.Data()); sl@0: // CChannelAndSampleRateConverter returns the source length converted sl@0: // while the old API wants the destination generated, so change. sl@0: TInt result = aDstBuffer.Data().Length(); sl@0: return result; sl@0: } sl@0: sl@0: void CMMFForwardingChannelAndSampleRateConverter::Reset() sl@0: { sl@0: // need to check iRealConverter created. Won't be true during construction sl@0: if (iRealConverter) sl@0: { sl@0: iRealConverter->Reset(); sl@0: } sl@0: } sl@0: sl@0: TUint CMMFForwardingChannelAndSampleRateConverter::MaxConvertBufferSize(TUint aSrcBufferSize) sl@0: { sl@0: return TUint(iRealConverter->MaxConvertBufferSize(aSrcBufferSize)); sl@0: } sl@0: sl@0: // sl@0: // Old derivatives of CMMFChannelAndSampleRateConverter. These were previously returned by sl@0: // CreateConverterL(). Kept for BC, but no longer used by main code. sl@0: // sl@0: sl@0: TInt CMMFStereoToStereoRateConverter::Convert(const CMMFDataBuffer& aSrcBuffer, CMMFDataBuffer& aDstBuffer) sl@0: { sl@0: TInt32* aSrc = (TInt32*)aSrcBuffer.Data().Ptr(); sl@0: TInt32* aDst = (TInt32*)aDstBuffer.Data().Ptr(); sl@0: TUint aSamples = aSrcBuffer.Data().Length()/4; sl@0: sl@0: TInt32* src = aSrc; sl@0: TInt32* dst = aDst; sl@0: TInt32* limit=src+aSamples; sl@0: sl@0: // add left over from last buffer sl@0: TUint index = iIndex; sl@0: src = aSrc + (index>>16); sl@0: sl@0: while(src>16); sl@0: } sl@0: sl@0: // get amount by which index exceeded end of buffer sl@0: // so that we can add it back to start of next buffer sl@0: iIndex = index - (aSamples << 16); sl@0: sl@0: // return sample byte count and setup output buffer sl@0: TInt length = (dst-(TInt32*)aDst)*4; //dealing with 32bit values so multiply by 4 for bytes sl@0: aDstBuffer.Data().SetLength(length); //adjust length of destination buffer sl@0: return (length); sl@0: } sl@0: sl@0: TInt CMMFMonoToStereoRateConverter::Convert(const CMMFDataBuffer& aSrcBuffer, CMMFDataBuffer& aDstBuffer) sl@0: { sl@0: TInt16* aSrc = (TInt16*)aSrcBuffer.Data().Ptr(); sl@0: TInt16* aDst = (TInt16*)aDstBuffer.Data().Ptr(); sl@0: TUint aSamples = aSrcBuffer.Data().Length()/2; sl@0: sl@0: TInt16* src = aSrc; sl@0: TInt16* dst = aDst; sl@0: TInt16* limit=aSrc+aSamples; sl@0: sl@0: // add left over from last buffer sl@0: TUint index = iIndex; sl@0: src = aSrc + (index>>16); sl@0: sl@0: while(src>16); sl@0: } sl@0: sl@0: // get amount by which index exceeded end of buffer sl@0: // so that we can add it back to start of next buffer sl@0: iIndex = index - (aSamples << 16); sl@0: sl@0: // return sample byte count and setup output buffer sl@0: TInt length = (dst-aDst) * 2; // size in bytes sl@0: aDstBuffer.Data().SetLength(length); //adjust length of destination buffer sl@0: return (length); sl@0: } sl@0: sl@0: sl@0: TUint CMMFMonoToStereoRateConverter::MaxConvertBufferSize(TUint aSrcBufferSize) sl@0: { sl@0: return aSrcBufferSize*2; sl@0: } sl@0: sl@0: sl@0: sl@0: TInt CMMFMonoToMonoRateConverter::Convert(const CMMFDataBuffer& aSrcBuffer, CMMFDataBuffer& aDstBuffer) sl@0: { sl@0: TInt16* aSrc = (TInt16*)aSrcBuffer.Data().Ptr(); sl@0: TInt16* aDst = (TInt16*)aDstBuffer.Data().Ptr(); sl@0: TUint aSamples = aSrcBuffer.Data().Length()/2; sl@0: sl@0: TInt16* src = aSrc; sl@0: TInt16* dst = aDst; sl@0: TInt16* limit=aSrc+aSamples; //*2 ??? sl@0: sl@0: // add left over from last buffer sl@0: TUint index = iIndex; sl@0: src = aSrc + (index>>16); sl@0: sl@0: while(src>16); sl@0: } sl@0: sl@0: // get amount by which index exceeded end of buffer sl@0: // so that we can add it back to start of next buffer sl@0: iIndex = index - (aSamples << 16); sl@0: sl@0: // return sample byte count and setup output buffer sl@0: TInt length = (dst-aDst)*2; // size in bytes sl@0: aDstBuffer.Data().SetLength(length); //adjust length of destination buffer sl@0: return (length); sl@0: } sl@0: sl@0: //This method takes the left and right sample of interleaved PCM and sums it, then divides by 2 sl@0: TInt CMMFStereoToMonoRateConverter::Convert(const CMMFDataBuffer& aSrcBuffer, CMMFDataBuffer& aDstBuffer) sl@0: { sl@0: TInt16* aSrc = (TInt16*)aSrcBuffer.Data().Ptr(); sl@0: TInt16* aDst = (TInt16*)aDstBuffer.Data().Ptr(); sl@0: TUint aSamples = aSrcBuffer.Data().Length()/4; sl@0: sl@0: TInt16* src = aSrc; sl@0: TInt16* limit=aSrc+aSamples*2; //because 1 sample = two TInt16s sl@0: sl@0: // add left over from last buffer sl@0: TUint index = iIndex; sl@0: src = aSrc + (index>>16)*2; sl@0: sl@0: TInt length = 0; sl@0: sl@0: while(src>16)*2; sl@0: length++; sl@0: } sl@0: // get amount by which index exceeded end of buffer sl@0: // so that we can add it back to start of next buffer sl@0: iIndex = index - (aSamples << 16); sl@0: sl@0: // return sample byte count and setup output buffer sl@0: aDstBuffer.Data().SetLength(length * 2); //adjust length of destination buffer sl@0: return (length); sl@0: } sl@0: sl@0: sl@0: TUint CMMFStereoToMonoRateConverter::MaxConvertBufferSize(TUint aSrcBufferSize) sl@0: { sl@0: TUint size = aSrcBufferSize/2; sl@0: size += aSrcBufferSize & 1; //avoid round down error sl@0: return size; sl@0: } sl@0: sl@0: //This method takes the left and right sample of interleaved PCM and sums it, then divides by 2 sl@0: TInt CMMFStereoToMonoConverter::Convert(const CMMFDataBuffer& aSrcBuffer, CMMFDataBuffer& aDstBuffer) sl@0: { sl@0: TInt16* aSrc = (TInt16*)aSrcBuffer.Data().Ptr(); sl@0: TInt16* aDst = (TInt16*)aDstBuffer.Data().Ptr(); sl@0: TUint aSamples = aSrcBuffer.Data().Length()/4; sl@0: for (TUint i=0;i