1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmdevicefw/mdf/src/audio/mdasoundadapter/mdasoundadapterbody.h Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,639 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#ifndef MDASOUNDADAPTERBODY_H
1.20 +#define MDASOUNDADAPTERBODY_H
1.21 +
1.22 +#include "mdasoundadapter.h"
1.23 +#include <d32soundsc.h>
1.24 +#include <e32base.h>
1.25 +#include <e32std.h>
1.26 +
1.27 +/**
1.28 +Panic category and codes for the mdasoundadapter
1.29 +*/
1.30 +_LIT(KSoundAdapterPanicCategory, "mdasoundadapter");
1.31 +enum TSoundAdapterPanicCodes
1.32 + {
1.33 + EDeviceNotOpened,
1.34 + EPanicPartialBufferConverterNotSupported,
1.35 + EBadState,
1.36 + ENoClientPlayRequest,
1.37 + EFifoEmpty,
1.38 + EFifoFull
1.39 + };
1.40 +
1.41 +//Structure used to map samples per second to the corresponding enums in RSoundSc
1.42 +struct TSampleRateEnumTable
1.43 + {
1.44 + TInt iRate;
1.45 + TSoundRate iRateEnum;
1.46 + TUint iRateConstant;
1.47 + };
1.48 +
1.49 +//Table that maps given samples per second to the corresponding enums in RSoundSc
1.50 +const TSampleRateEnumTable KRateEnumLookup[] =
1.51 + {
1.52 + {48000,ESoundRate48000Hz,KSoundRate48000Hz},
1.53 + {44100,ESoundRate44100Hz,KSoundRate44100Hz},
1.54 + {32000,ESoundRate32000Hz,KSoundRate32000Hz},
1.55 + {24000,ESoundRate24000Hz,KSoundRate24000Hz},
1.56 + {22050,ESoundRate22050Hz,KSoundRate22050Hz},
1.57 + {16000,ESoundRate16000Hz,KSoundRate16000Hz},
1.58 + {12000,ESoundRate12000Hz,KSoundRate12000Hz},
1.59 + {11025,ESoundRate11025Hz,KSoundRate11025Hz},
1.60 + {8000, ESoundRate8000Hz, KSoundRate8000Hz}
1.61 + };
1.62 +//Structure used to map linear value of the volume to the decibel value.
1.63 +struct TLinearToDbTable
1.64 + {
1.65 + TInt iLiniearValue;
1.66 + TInt iDBValue;
1.67 + };
1.68 +
1.69 +
1.70 +//Table that maps given linear value of volume to the corresponding decibel value.
1.71 +const TLinearToDbTable KLinerToDbConstantLookup[] =
1.72 + {
1.73 + {0,0},
1.74 + {1,158},
1.75 + {2,170},
1.76 + {3,177},
1.77 + {4,182},
1.78 + {5,186},
1.79 + {6,189},
1.80 + {7,192},
1.81 + {8,194},
1.82 + {9,196},
1.83 + {10,198},
1.84 + {11,200},
1.85 + {12,201},
1.86 + {13,203},
1.87 + {14,204},
1.88 + {15,205},
1.89 + {16,206},
1.90 + {17,207},
1.91 + {18,208},
1.92 + {19,209},
1.93 + {20,210},
1.94 + {21,211},
1.95 + {22,212},
1.96 + {23,213},
1.97 + {24,213},
1.98 + {25,214},
1.99 + {26,215},
1.100 + {27,215},
1.101 + {28,216},
1.102 + {29,217},
1.103 + {30,217},
1.104 + {31,218},
1.105 + {32,218},
1.106 + {33,219},
1.107 + {34,219},
1.108 + {35,220},
1.109 + {36,220},
1.110 + {37,221},
1.111 + {38,221},
1.112 + {39,222},
1.113 + {40,222},
1.114 + {41,223},
1.115 + {42,223},
1.116 + {43,224},
1.117 + {44,224},
1.118 + {45,224},
1.119 + {46,225},
1.120 + {47,225},
1.121 + {48,225},
1.122 + {49,226},
1.123 + {50,226},
1.124 + {51,226},
1.125 + {52,227},
1.126 + {53,227},
1.127 + {54,227},
1.128 + {55,228},
1.129 + {56,228},
1.130 + {57,228},
1.131 + {58,229},
1.132 + {59,229},
1.133 + {60,229},
1.134 + {61,230},
1.135 + {62,230},
1.136 + {63,230},
1.137 + {64,230},
1.138 + {65,231},
1.139 + {66,231},
1.140 + {67,231},
1.141 + {68,231},
1.142 + {69,232},
1.143 + {70,232},
1.144 + {71,232},
1.145 + {72,232},
1.146 + {73,233},
1.147 + {74,233},
1.148 + {75,233},
1.149 + {76,233},
1.150 + {77,234},
1.151 + {78,234},
1.152 + {79,234},
1.153 + {80,234},
1.154 + {81,235},
1.155 + {82,235},
1.156 + {83,235},
1.157 + {84,235},
1.158 + {85,235},
1.159 + {86,236},
1.160 + {87,236},
1.161 + {88,236},
1.162 + {89,236},
1.163 + {90,236},
1.164 + {91,237},
1.165 + {92,237},
1.166 + {93,237},
1.167 + {94,237},
1.168 + {95,237},
1.169 + {96,237},
1.170 + {97,238},
1.171 + {98,238},
1.172 + {99,238},
1.173 + {100,238},
1.174 + {101,238},
1.175 + {102,239},
1.176 + {103,239},
1.177 + {104,239},
1.178 + {105,239},
1.179 + {106,239},
1.180 + {107,239},
1.181 + {108,240},
1.182 + {109,240},
1.183 + {110,240},
1.184 + {111,240},
1.185 + {112,240},
1.186 + {113,240},
1.187 + {114,240},
1.188 + {115,241},
1.189 + {116,241},
1.190 + {117,241},
1.191 + {118,241},
1.192 + {119,241},
1.193 + {120,241},
1.194 + {121,241},
1.195 + {122,242},
1.196 + {123,242},
1.197 + {124,242},
1.198 + {125,242},
1.199 + {126,242},
1.200 + {127,242},
1.201 + {128,242},
1.202 + {129,243},
1.203 + {130,243},
1.204 + {131,243},
1.205 + {132,243},
1.206 + {133,243},
1.207 + {134,243},
1.208 + {135,243},
1.209 + {136,244},
1.210 + {137,244},
1.211 + {138,244},
1.212 + {139,244},
1.213 + {140,244},
1.214 + {141,244},
1.215 + {142,244},
1.216 + {143,244},
1.217 + {144,245},
1.218 + {145,245},
1.219 + {146,245},
1.220 + {147,245},
1.221 + {148,245},
1.222 + {149,245},
1.223 + {150,245},
1.224 + {151,245},
1.225 + {152,245},
1.226 + {153,246},
1.227 + {154,246},
1.228 + {155,246},
1.229 + {156,246},
1.230 + {157,246},
1.231 + {158,246},
1.232 + {159,246},
1.233 + {160,246},
1.234 + {161,246},
1.235 + {162,247},
1.236 + {163,247},
1.237 + {164,247},
1.238 + {165,247},
1.239 + {166,247},
1.240 + {167,247},
1.241 + {168,247},
1.242 + {169,247},
1.243 + {170,247},
1.244 + {171,247},
1.245 + {172,248},
1.246 + {173,248},
1.247 + {174,248},
1.248 + {175,248},
1.249 + {176,248},
1.250 + {177,248},
1.251 + {178,248},
1.252 + {179,248},
1.253 + {180,248},
1.254 + {181,248},
1.255 + {182,249},
1.256 + {183,249},
1.257 + {184,249},
1.258 + {185,249},
1.259 + {186,249},
1.260 + {187,249},
1.261 + {188,249},
1.262 + {189,249},
1.263 + {190,249},
1.264 + {191,249},
1.265 + {192,250},
1.266 + {193,250},
1.267 + {194,250},
1.268 + {195,250},
1.269 + {196,250},
1.270 + {197,250},
1.271 + {198,250},
1.272 + {199,250},
1.273 + {200,250},
1.274 + {201,250},
1.275 + {202,250},
1.276 + {203,250},
1.277 + {204,251},
1.278 + {205,251},
1.279 + {206,251},
1.280 + {207,251},
1.281 + {208,251},
1.282 + {209,251},
1.283 + {210,251},
1.284 + {211,251},
1.285 + {212,251},
1.286 + {213,251},
1.287 + {214,251},
1.288 + {215,251},
1.289 + {216,252},
1.290 + {217,252},
1.291 + {218,252},
1.292 + {219,252},
1.293 + {220,252},
1.294 + {221,252},
1.295 + {222,252},
1.296 + {223,252},
1.297 + {224,252},
1.298 + {225,252},
1.299 + {226,252},
1.300 + {227,252},
1.301 + {228,252},
1.302 + {229,253},
1.303 + {230,253},
1.304 + {231,253},
1.305 + {232,253},
1.306 + {233,253},
1.307 + {234,253},
1.308 + {235,253},
1.309 + {236,253},
1.310 + {237,253},
1.311 + {238,253},
1.312 + {239,253},
1.313 + {240,253},
1.314 + {241,253},
1.315 + {242,254},
1.316 + {243,254},
1.317 + {244,254},
1.318 + {245,254},
1.319 + {246,254},
1.320 + {247,254},
1.321 + {248,254},
1.322 + {249,254},
1.323 + {250,254},
1.324 + {251,254},
1.325 + {252,254},
1.326 + {253,254},
1.327 + {254,254},
1.328 + {255,254}
1.329 + };
1.330 +
1.331 +// Total Number of sample rates
1.332 +const TUint KNumSampleRates = 9;
1.333 +// Number of shared chunk buffers used for playing
1.334 +// Each buffer is permanently mapped, via an index number, to a particular buffer in the chunk
1.335 +// The esoundsc.ldd can only handle a max of 8 pending play requests, therefore no point in having
1.336 +// more than 8 play buffers...
1.337 +const TUint KPlaySharedChunkBuffers = 8;
1.338 +// Size of RSoundSc play buffers
1.339 +const TUint KPlaySharedChunkBufferSize = 4096;
1.340 +
1.341 +//Number of shared chunk buffers used for recording
1.342 +const TUint KRecordMaxSharedChunkBuffers = 8;
1.343 +// Size of RSoundSc record buffers
1.344 +const TUint KRecordSharedChunkBufferSize = 4096;
1.345 +
1.346 +//Shared chunk driver does not support max. buffer size. 16K is given in order to simulate the old driver behavior.
1.347 +const TUint KMaxBufferSize = 0x4000;
1.348 +
1.349 +class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase
1.350 + {
1.351 +public:
1.352 + TInt iBufferOffsetList[KPlaySharedChunkBuffers];
1.353 + };
1.354 +
1.355 +class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase
1.356 + {
1.357 +public:
1.358 + TInt iBufferOffsetList[KRecordMaxSharedChunkBuffers];
1.359 + };
1.360 +
1.361 +class CChannelAndSampleRateConverter; // forward dec
1.362 +
1.363 +GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration
1.364 +
1.365 +// RFifo class which manages a fifo of up to COUNT items of type T
1.366 +template<typename T, TUint32 COUNT> class RFifo
1.367 + {
1.368 +public:
1.369 + RFifo()
1.370 + : iWriteIndex(0), iReadIndex(0)
1.371 + {}
1.372 + TBool IsEmpty() const
1.373 + {
1.374 + return iWriteIndex == iReadIndex;
1.375 + }
1.376 + TBool IsFull() const
1.377 + {
1.378 + // Full if writing one more item would make iWriteIndex equal to iReadIndex
1.379 + TUint32 next = NextIndex(iWriteIndex);
1.380 + return next == iReadIndex;
1.381 + }
1.382 + /// Push item into FIFO. Does not take ownership. Will PANIC with EFifoFull if full.
1.383 + void Push(const T &aItem)
1.384 + {
1.385 + if(IsFull())
1.386 + {
1.387 + Panic(EFifoFull);
1.388 + }
1.389 + iFifo[iWriteIndex] = aItem;
1.390 + iWriteIndex = NextIndex(iWriteIndex);
1.391 + }
1.392 + /// Pop item from FIFO. Will PANIC with EFifoEmpty if empty
1.393 + T Pop()
1.394 + {
1.395 + if(IsEmpty())
1.396 + {
1.397 + Panic(EFifoEmpty);
1.398 + }
1.399 + TUint32 tmp = iReadIndex;
1.400 + iReadIndex = NextIndex(iReadIndex);
1.401 + return iFifo[tmp];
1.402 + }
1.403 +
1.404 + /// Peek first item from FIFO. Will PANIC with EFifoEmpty if empty
1.405 + T Peek()
1.406 + {
1.407 + if(IsEmpty())
1.408 + {
1.409 + Panic(EFifoEmpty);
1.410 + }
1.411 + return iFifo[iReadIndex];
1.412 + }
1.413 + TUint Length() const
1.414 + {
1.415 + TUint len;
1.416 + if(iWriteIndex >= iReadIndex)
1.417 + {
1.418 + len = iWriteIndex - iReadIndex;
1.419 + }
1.420 + else
1.421 + {
1.422 + len = COUNT+1 - (iReadIndex - iWriteIndex);
1.423 + }
1.424 + return len;
1.425 + }
1.426 +private:
1.427 + TUint32 NextIndex(TUint32 aIndex) const
1.428 + {
1.429 + ++aIndex;
1.430 + aIndex %= (COUNT+1);
1.431 + return aIndex;
1.432 + }
1.433 + T iFifo[COUNT+1];
1.434 + TUint32 iWriteIndex;
1.435 + TUint32 iReadIndex;
1.436 + };
1.437 +
1.438 +
1.439 +
1.440 +//Body class for the adapter
1.441 +NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase
1.442 + {
1.443 +public:
1.444 + //This class handles the play/record completions from the new sound driver
1.445 + NONSHARABLE_CLASS( CPlayer ) : public CActive
1.446 + {
1.447 + public:
1.448 + explicit CPlayer(TInt aPriority, RMdaDevSound::CBody& aParent, TInt aIndex);
1.449 + ~CPlayer();
1.450 + void RunL();
1.451 + TInt RunError(TInt aError);
1.452 + void DoCancel();
1.453 + void PlayData(TUint aChunkOffset, TInt aLength);
1.454 +
1.455 + TUint GetPlayerIndex() const;
1.456 +
1.457 + private:
1.458 + RMdaDevSound::CBody& iParent;
1.459 + const TUint iIndex; // index of this object in parent
1.460 +
1.461 + TInt iBufferOffset;
1.462 + TInt iBufferLength;
1.463 + };
1.464 +
1.465 +
1.466 + NONSHARABLE_CLASS( CRecorder ) : public CActive
1.467 + {
1.468 + public:
1.469 + explicit CRecorder(TInt aPriority, RMdaDevSound::CBody& aParent);
1.470 + ~CRecorder();
1.471 + void RunL();
1.472 + TInt RunError(TInt aError);
1.473 + void DoCancel();
1.474 + void RecordData(TInt& aLength);
1.475 +
1.476 + private:
1.477 + RMdaDevSound::CBody& iParent;
1.478 +
1.479 + TInt iBufferOffset;
1.480 + TInt iBufferLength;
1.481 + };
1.482 +
1.483 + enum TStateEnum
1.484 + {
1.485 + ENotReady,
1.486 + EStopped,
1.487 + ERecording,
1.488 + ERecordingPausedInHw,
1.489 + ERecordingPausedInSw,
1.490 + EPlaying,
1.491 + EPlayingPausedInHw, // ie. Play request pending on h/w and paused
1.492 + EPlayingPausedInSw, // ie. Driver not playing or paused
1.493 + EPlayingUnderrun
1.494 + };
1.495 +
1.496 + NONSHARABLE_CLASS( TState )
1.497 + {
1.498 + public:
1.499 + TState(TStateEnum aState) : iState(aState) {}
1.500 + const TText8 *Name() const;
1.501 + TState &operator=(TStateEnum aNewState);
1.502 + operator TStateEnum() const { return iState; }
1.503 + private:
1.504 + TStateEnum iState;
1.505 + };
1.506 +
1.507 + class TFormatData
1.508 + {
1.509 + public:
1.510 + inline TFormatData():
1.511 + iSampleRate(8000), iRequestedChannels(1) // default
1.512 + {
1.513 + }
1.514 + public:
1.515 + CChannelAndSampleRateConverter* iConverter;
1.516 + TInt iSampleRate;
1.517 + TInt iActualRate;
1.518 + TInt iRequestedChannels;
1.519 + TInt iActualChannels;
1.520 + };
1.521 +
1.522 +public:
1.523 + ~CBody();
1.524 + static CBody* NewL();
1.525 + TInt Open(TInt aUnit=KNullUnit);
1.526 + TVersion VersionRequired() const;
1.527 + TInt IsMdaSound();
1.528 + void PlayFormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported);
1.529 + void GetPlayFormat(TCurrentSoundFormatBuf& aFormat);
1.530 + TInt SetPlayFormat(const TCurrentSoundFormatBuf& aFormat);
1.531 + TInt PlayVolume();
1.532 + void SetPlayVolume(TInt aVolume);
1.533 + void SetVolume(TInt aLogarithmicVolume);
1.534 + void CancelPlayData();
1.535 + void RecordFormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported);
1.536 + void GetRecordFormat(TCurrentSoundFormatBuf& aFormat);
1.537 + TInt SetRecordFormat(const TCurrentSoundFormatBuf& aFormat);
1.538 + TInt RecordLevel();
1.539 + void SetRecordLevel(TInt aLevel);
1.540 + void CancelRecordData();
1.541 + void FlushRecordBuffer();
1.542 + TInt BytesPlayed();
1.543 + void ResetBytesPlayed();
1.544 + void PausePlayBuffer();
1.545 + void ResumePlaying();
1.546 + void PauseRecordBuffer();
1.547 + void ResumeRecording();
1.548 + TInt GetTimePlayed(TTimeIntervalMicroSeconds& aTimePlayed);
1.549 + void Close();
1.550 + TInt Handle();
1.551 + void PlayData(TRequestStatus& aStatus,const TDesC8& aData);
1.552 + void RecordData(TRequestStatus& aStatus,TDes8& aData);
1.553 + void NotifyRecordError(TRequestStatus& aStatus);
1.554 + void NotifyPlayError(TRequestStatus& aStatus);
1.555 + void CancelNotifyPlayError();
1.556 + void CancelNotifyRecordError();
1.557 + void FlushPlayBuffer();
1.558 + //internal methods added to reduce the code
1.559 + void FormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported, RSoundSc& aDevice);
1.560 + void GetFormat(TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, const TFormatData &aFormatData);
1.561 + TInt SetFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
1.562 +
1.563 + //for players
1.564 + void SoundDeviceError(TInt aError);
1.565 + RSoundSc& PlaySoundDevice();
1.566 + RSoundSc& RecordSoundDevice();
1.567 + const TState &State() const;
1.568 + void BufferFilled(TInt aError);
1.569 +
1.570 + // Called whenever a player becomes inactive.
1.571 + // This includes driver request ok, driver request failed, CPlayer:::RunError invoked.
1.572 + void PlayRequestHasCompleted(CPlayer *aPlayer, TInt aStatus, TBool aDueToCancelCommand);
1.573 +
1.574 +private:
1.575 + CBody();
1.576 + void ConstructL();
1.577 +
1.578 + TInt NegotiateFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
1.579 +
1.580 + void StartPlayersAndUpdateState();
1.581 + void StartRecordRequest();
1.582 +
1.583 + const char *StateName() const;
1.584 +
1.585 + TBool InRecordMode() const;
1.586 + TBool InPlayMode() const;
1.587 +
1.588 + TUint32 CurrentTimeInMsec() const;
1.589 + TUint64 BytesPlayed64();
1.590 +
1.591 +private:
1.592 + RSoundSc iPlaySoundDevice;
1.593 + RChunk iPlayChunk;//handle to the shared chunk
1.594 + RSoundSc iRecordSoundDevice;
1.595 + RChunk iRecordChunk;//handle to the shared chunk
1.596 + TState iState;
1.597 +
1.598 + //Playing Properties
1.599 + TPlaySharedChunkBufConfig iPlayBufferConfig;
1.600 + TInt iDeviceBufferLength;
1.601 +
1.602 + //Stores the status of CDataPathPlayer
1.603 + TRequestStatus* iClientPlayStatus;
1.604 + TPtrC8 iClientPlayData;
1.605 + //Stores the status of CSoundDevPlayErrorReceiver
1.606 + TRequestStatus* iClientPlayErrorStatus;
1.607 + RBuf8 iConvertedPlayData;
1.608 + RBuf8 iSavedTrailingData;
1.609 +
1.610 + CPlayer* iPlayers[KPlaySharedChunkBuffers];
1.611 + RFifo<CPlayer *, KPlaySharedChunkBuffers> iFreePlayers;
1.612 + RFifo<TUint32, KPlaySharedChunkBuffers> iActivePlayRequestSizes;
1.613 +
1.614 + TInt iRequestMinSize;
1.615 + TUint iRequestMinMask;
1.616 +
1.617 + //Recording Properties
1.618 + TRecordSharedChunkBufConfig iRecordBufferConfig;
1.619 + TInt iBufferOffset;
1.620 + TInt iBufferLength;
1.621 +
1.622 + //Stores the status of CDataPathRecorder
1.623 + TRequestStatus* iClientRecordStatus;
1.624 + //Stores the status of CSoundDevRecordErrorReceiver
1.625 + TRequestStatus* iClientRecordErrorStatus;
1.626 + TDes8* iClientRecordData;//stores the data pointer from datapath recorder
1.627 + RBuf8 iBufferedRecordData; // Used if RSoundSc returns more data than current client request requires.
1.628 +
1.629 + CRecorder* iRecorder; // We only need one recorder. The driver will buffer data for us.
1.630 +
1.631 + TBool iUnderFlowReportedSinceLastPlayOrRecordRequest;
1.632 +
1.633 + TUint64 iBytesPlayed;
1.634 + TUint32 iNTickPeriodInUsec;
1.635 + TUint32 iStartTime; // Time when previous driver PlayData completed (or first was issued) in msec
1.636 + TUint32 iPauseTime; // Time when pause started in msec
1.637 + TUint64 iPausedBytesPlayed;
1.638 +
1.639 + TFormatData iPlayFormatData;
1.640 + TFormatData iRecordFormatData;
1.641 + };
1.642 +#endif