diff -r 000000000000 -r 58be5850fb6c omxilcomp/omxilaudioemulator/pcmrenderer/src/mdasoundadapterbody.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omxilcomp/omxilaudioemulator/pcmrenderer/src/mdasoundadapterbody.h Thu Sep 02 20:13:57 2010 +0300 @@ -0,0 +1,639 @@ +// Copyright (c) 2007-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: +// + +#ifndef MDASOUNDADAPTERBODY_H +#define MDASOUNDADAPTERBODY_H + +#include "mdasoundadapter.h" +#include +#include +#include + +/** +Panic category and codes for the mdasoundadapter +*/ +_LIT(KSoundAdapterPanicCategory, "mdasoundadapter"); +enum TSoundAdapterPanicCodes + { + EDeviceNotOpened, + EPanicPartialBufferConverterNotSupported, + EBadState, + ENoClientPlayRequest, + EFifoEmpty, + EFifoFull + }; + +//Structure used to map samples per second to the corresponding enums in RSoundSc +struct TSampleRateEnumTable + { + TInt iRate; + TSoundRate iRateEnum; + TUint iRateConstant; + }; + +//Table that maps given samples per second to the corresponding enums in RSoundSc +const TSampleRateEnumTable KRateEnumLookup[] = + { + {48000,ESoundRate48000Hz,KSoundRate48000Hz}, + {44100,ESoundRate44100Hz,KSoundRate44100Hz}, + {32000,ESoundRate32000Hz,KSoundRate32000Hz}, + {24000,ESoundRate24000Hz,KSoundRate24000Hz}, + {22050,ESoundRate22050Hz,KSoundRate22050Hz}, + {16000,ESoundRate16000Hz,KSoundRate16000Hz}, + {12000,ESoundRate12000Hz,KSoundRate12000Hz}, + {11025,ESoundRate11025Hz,KSoundRate11025Hz}, + {8000, ESoundRate8000Hz, KSoundRate8000Hz} + }; +//Structure used to map linear value of the volume to the decibel value. +struct TLinearToDbTable + { + TInt iLiniearValue; + TInt iDBValue; + }; + + +//Table that maps given linear value of volume to the corresponding decibel value. +const TLinearToDbTable KLinerToDbConstantLookup[] = + { + {0,0}, + {1,158}, + {2,170}, + {3,177}, + {4,182}, + {5,186}, + {6,189}, + {7,192}, + {8,194}, + {9,196}, + {10,198}, + {11,200}, + {12,201}, + {13,203}, + {14,204}, + {15,205}, + {16,206}, + {17,207}, + {18,208}, + {19,209}, + {20,210}, + {21,211}, + {22,212}, + {23,213}, + {24,213}, + {25,214}, + {26,215}, + {27,215}, + {28,216}, + {29,217}, + {30,217}, + {31,218}, + {32,218}, + {33,219}, + {34,219}, + {35,220}, + {36,220}, + {37,221}, + {38,221}, + {39,222}, + {40,222}, + {41,223}, + {42,223}, + {43,224}, + {44,224}, + {45,224}, + {46,225}, + {47,225}, + {48,225}, + {49,226}, + {50,226}, + {51,226}, + {52,227}, + {53,227}, + {54,227}, + {55,228}, + {56,228}, + {57,228}, + {58,229}, + {59,229}, + {60,229}, + {61,230}, + {62,230}, + {63,230}, + {64,230}, + {65,231}, + {66,231}, + {67,231}, + {68,231}, + {69,232}, + {70,232}, + {71,232}, + {72,232}, + {73,233}, + {74,233}, + {75,233}, + {76,233}, + {77,234}, + {78,234}, + {79,234}, + {80,234}, + {81,235}, + {82,235}, + {83,235}, + {84,235}, + {85,235}, + {86,236}, + {87,236}, + {88,236}, + {89,236}, + {90,236}, + {91,237}, + {92,237}, + {93,237}, + {94,237}, + {95,237}, + {96,237}, + {97,238}, + {98,238}, + {99,238}, + {100,238}, + {101,238}, + {102,239}, + {103,239}, + {104,239}, + {105,239}, + {106,239}, + {107,239}, + {108,240}, + {109,240}, + {110,240}, + {111,240}, + {112,240}, + {113,240}, + {114,240}, + {115,241}, + {116,241}, + {117,241}, + {118,241}, + {119,241}, + {120,241}, + {121,241}, + {122,242}, + {123,242}, + {124,242}, + {125,242}, + {126,242}, + {127,242}, + {128,242}, + {129,243}, + {130,243}, + {131,243}, + {132,243}, + {133,243}, + {134,243}, + {135,243}, + {136,244}, + {137,244}, + {138,244}, + {139,244}, + {140,244}, + {141,244}, + {142,244}, + {143,244}, + {144,245}, + {145,245}, + {146,245}, + {147,245}, + {148,245}, + {149,245}, + {150,245}, + {151,245}, + {152,245}, + {153,246}, + {154,246}, + {155,246}, + {156,246}, + {157,246}, + {158,246}, + {159,246}, + {160,246}, + {161,246}, + {162,247}, + {163,247}, + {164,247}, + {165,247}, + {166,247}, + {167,247}, + {168,247}, + {169,247}, + {170,247}, + {171,247}, + {172,248}, + {173,248}, + {174,248}, + {175,248}, + {176,248}, + {177,248}, + {178,248}, + {179,248}, + {180,248}, + {181,248}, + {182,249}, + {183,249}, + {184,249}, + {185,249}, + {186,249}, + {187,249}, + {188,249}, + {189,249}, + {190,249}, + {191,249}, + {192,250}, + {193,250}, + {194,250}, + {195,250}, + {196,250}, + {197,250}, + {198,250}, + {199,250}, + {200,250}, + {201,250}, + {202,250}, + {203,250}, + {204,251}, + {205,251}, + {206,251}, + {207,251}, + {208,251}, + {209,251}, + {210,251}, + {211,251}, + {212,251}, + {213,251}, + {214,251}, + {215,251}, + {216,252}, + {217,252}, + {218,252}, + {219,252}, + {220,252}, + {221,252}, + {222,252}, + {223,252}, + {224,252}, + {225,252}, + {226,252}, + {227,252}, + {228,252}, + {229,253}, + {230,253}, + {231,253}, + {232,253}, + {233,253}, + {234,253}, + {235,253}, + {236,253}, + {237,253}, + {238,253}, + {239,253}, + {240,253}, + {241,253}, + {242,254}, + {243,254}, + {244,254}, + {245,254}, + {246,254}, + {247,254}, + {248,254}, + {249,254}, + {250,254}, + {251,254}, + {252,254}, + {253,254}, + {254,254}, + {255,254} + }; + +// Total Number of sample rates +const TUint KNumSampleRates = 9; +// Number of shared chunk buffers used for playing +// Each buffer is permanently mapped, via an index number, to a particular buffer in the chunk +// The esoundsc.ldd can only handle a max of 8 pending play requests, therefore no point in having +// more than 8 play buffers... +const TUint KPlaySharedChunkBuffers = 8; +// Size of RSoundSc play buffers +const TUint KPlaySharedChunkBufferSize = 4096; + +//Number of shared chunk buffers used for recording +const TUint KRecordMaxSharedChunkBuffers = 8; +// Size of RSoundSc record buffers +const TUint KRecordSharedChunkBufferSize = 4096; + +//Shared chunk driver does not support max. buffer size. 16K is given in order to simulate the old driver behavior. +const TUint KMaxBufferSize = 0x4000; + +class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase + { +public: + TInt iBufferOffsetList[KPlaySharedChunkBuffers]; + }; + +class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase + { +public: + TInt iBufferOffsetList[KRecordMaxSharedChunkBuffers]; + }; + +class CChannelAndSampleRateConverter; // forward dec + +GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration + +// RFifo class which manages a fifo of up to COUNT items of type T +template class RFifo + { +public: + RFifo() + : iWriteIndex(0), iReadIndex(0) + {} + TBool IsEmpty() const + { + return iWriteIndex == iReadIndex; + } + TBool IsFull() const + { + // Full if writing one more item would make iWriteIndex equal to iReadIndex + TUint32 next = NextIndex(iWriteIndex); + return next == iReadIndex; + } + /// Push item into FIFO. Does not take ownership. Will PANIC with EFifoFull if full. + void Push(const T &aItem) + { + if(IsFull()) + { + Panic(EFifoFull); + } + iFifo[iWriteIndex] = aItem; + iWriteIndex = NextIndex(iWriteIndex); + } + /// Pop item from FIFO. Will PANIC with EFifoEmpty if empty + T Pop() + { + if(IsEmpty()) + { + Panic(EFifoEmpty); + } + TUint32 tmp = iReadIndex; + iReadIndex = NextIndex(iReadIndex); + return iFifo[tmp]; + } + + /// Peek first item from FIFO. Will PANIC with EFifoEmpty if empty + T Peek() + { + if(IsEmpty()) + { + Panic(EFifoEmpty); + } + return iFifo[iReadIndex]; + } + TUint Length() const + { + TUint len; + if(iWriteIndex >= iReadIndex) + { + len = iWriteIndex - iReadIndex; + } + else + { + len = COUNT+1 - (iReadIndex - iWriteIndex); + } + return len; + } +private: + TUint32 NextIndex(TUint32 aIndex) const + { + ++aIndex; + aIndex %= (COUNT+1); + return aIndex; + } + T iFifo[COUNT+1]; + TUint32 iWriteIndex; + TUint32 iReadIndex; + }; + + + +//Body class for the adapter +NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase + { +public: + //This class handles the play/record completions from the new sound driver + NONSHARABLE_CLASS( CPlayer ) : public CActive + { + public: + explicit CPlayer(TInt aPriority, RMdaDevSound::CBody& aParent, TInt aIndex); + ~CPlayer(); + void RunL(); + TInt RunError(TInt aError); + void DoCancel(); + void PlayData(TUint aChunkOffset, TInt aLength); + + TUint GetPlayerIndex() const; + + private: + RMdaDevSound::CBody& iParent; + const TUint iIndex; // index of this object in parent + + TInt iBufferOffset; + TInt iBufferLength; + }; + + + NONSHARABLE_CLASS( CRecorder ) : public CActive + { + public: + explicit CRecorder(TInt aPriority, RMdaDevSound::CBody& aParent); + ~CRecorder(); + void RunL(); + TInt RunError(TInt aError); + void DoCancel(); + void RecordData(TInt& aLength); + + private: + RMdaDevSound::CBody& iParent; + + TInt iBufferOffset; + TInt iBufferLength; + }; + + enum TStateEnum + { + ENotReady, + EStopped, + ERecording, + ERecordingPausedInHw, + ERecordingPausedInSw, + EPlaying, + EPlayingPausedInHw, // ie. Play request pending on h/w and paused + EPlayingPausedInSw, // ie. Driver not playing or paused + EPlayingUnderrun + }; + + NONSHARABLE_CLASS( TState ) + { + public: + TState(TStateEnum aState) : iState(aState) {} + const TText8 *Name() const; + TState &operator=(TStateEnum aNewState); + operator TStateEnum() const { return iState; } + private: + TStateEnum iState; + }; + + class TFormatData + { + public: + inline TFormatData(): + iSampleRate(8000), iRequestedChannels(1) // default + { + } + public: + CChannelAndSampleRateConverter* iConverter; + TInt iSampleRate; + TInt iActualRate; + TInt iRequestedChannels; + TInt iActualChannels; + }; + +public: + ~CBody(); + static CBody* NewL(); + TInt Open(TInt aUnit=KNullUnit); + TVersion VersionRequired() const; + TInt IsMdaSound(); + void PlayFormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported); + void GetPlayFormat(TCurrentSoundFormatBuf& aFormat); + TInt SetPlayFormat(const TCurrentSoundFormatBuf& aFormat); + TInt PlayVolume(); + void SetPlayVolume(TInt aVolume); + void SetVolume(TInt aLogarithmicVolume); + void CancelPlayData(); + void RecordFormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported); + void GetRecordFormat(TCurrentSoundFormatBuf& aFormat); + TInt SetRecordFormat(const TCurrentSoundFormatBuf& aFormat); + TInt RecordLevel(); + void SetRecordLevel(TInt aLevel); + void CancelRecordData(); + void FlushRecordBuffer(); + TInt BytesPlayed(); + void ResetBytesPlayed(); + void PausePlayBuffer(); + void ResumePlaying(); + void PauseRecordBuffer(); + void ResumeRecording(); + TInt GetTimePlayed(TTimeIntervalMicroSeconds& aTimePlayed); + void Close(); + TInt Handle(); + void PlayData(TRequestStatus& aStatus,const TDesC8& aData); + void RecordData(TRequestStatus& aStatus,TDes8& aData); + void NotifyRecordError(TRequestStatus& aStatus); + void NotifyPlayError(TRequestStatus& aStatus); + void CancelNotifyPlayError(); + void CancelNotifyRecordError(); + void FlushPlayBuffer(); + //internal methods added to reduce the code + void FormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported, RSoundSc& aDevice); + void GetFormat(TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, const TFormatData &aFormatData); + TInt SetFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData); + + //for players + void SoundDeviceError(TInt aError); + RSoundSc& PlaySoundDevice(); + RSoundSc& RecordSoundDevice(); + const TState &State() const; + void BufferFilled(TInt aError); + + // Called whenever a player becomes inactive. + // This includes driver request ok, driver request failed, CPlayer:::RunError invoked. + void PlayRequestHasCompleted(CPlayer *aPlayer, TInt aStatus, TBool aDueToCancelCommand); + +private: + CBody(); + void ConstructL(); + + TInt NegotiateFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData); + + void StartPlayersAndUpdateState(); + void StartRecordRequest(); + + const char *StateName() const; + + TBool InRecordMode() const; + TBool InPlayMode() const; + + TUint32 CurrentTimeInMsec() const; + TUint64 BytesPlayed64(); + +private: + RSoundSc iPlaySoundDevice; + RChunk iPlayChunk;//handle to the shared chunk + RSoundSc iRecordSoundDevice; + RChunk iRecordChunk;//handle to the shared chunk + TState iState; + + //Playing Properties + TPlaySharedChunkBufConfig iPlayBufferConfig; + TInt iDeviceBufferLength; + + //Stores the status of CDataPathPlayer + TRequestStatus* iClientPlayStatus; + TPtrC8 iClientPlayData; + //Stores the status of CSoundDevPlayErrorReceiver + TRequestStatus* iClientPlayErrorStatus; + RBuf8 iConvertedPlayData; + RBuf8 iSavedTrailingData; + + CPlayer* iPlayers[KPlaySharedChunkBuffers]; + RFifo iFreePlayers; + RFifo iActivePlayRequestSizes; + + TInt iRequestMinSize; + TUint iRequestMinMask; + + //Recording Properties + TRecordSharedChunkBufConfig iRecordBufferConfig; + TInt iBufferOffset; + TInt iBufferLength; + + //Stores the status of CDataPathRecorder + TRequestStatus* iClientRecordStatus; + //Stores the status of CSoundDevRecordErrorReceiver + TRequestStatus* iClientRecordErrorStatus; + TDes8* iClientRecordData;//stores the data pointer from datapath recorder + RBuf8 iBufferedRecordData; // Used if RSoundSc returns more data than current client request requires. + + CRecorder* iRecorder; // We only need one recorder. The driver will buffer data for us. + + TBool iUnderFlowReportedSinceLastPlayOrRecordRequest; + + TUint64 iBytesPlayed; + TUint32 iNTickPeriodInUsec; + TUint32 iStartTime; // Time when previous driver PlayData completed (or first was issued) in msec + TUint32 iPauseTime; // Time when pause started in msec + TUint64 iPausedBytesPlayed; + + TFormatData iPlayFormatData; + TFormatData iRecordFormatData; + }; +#endif