strmctxt.cpp
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:14k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. // -----------------------------------------------------------------------------
  2. //
  3. //      THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. //      ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  5. //      THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  6. //      PARTICULAR PURPOSE.
  7. //      Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
  8. //
  9. // -----------------------------------------------------------------------------
  10. #include "wavemain.h"
  11. HRESULT StreamContext::Open(DeviceContext *pDeviceContext, LPWAVEOPENDESC lpWOD, DWORD dwFlags)
  12. {
  13.     m_RefCount = 1;
  14.     m_pDeviceContext = pDeviceContext;
  15.     m_pfnCallback = (DRVCALLBACK *)lpWOD->dwCallback;
  16.     m_dwInstance  = lpWOD->dwInstance;
  17.     m_hWave       = lpWOD->hWave;
  18.     m_dwFlags     = dwFlags;
  19.     m_bRunning    = FALSE;
  20.     m_bForceSpeaker = FALSE;
  21.     // If it's a PCMWAVEFORMAT struct, it's smaller than a WAVEFORMATEX struct (it doesn't have the cbSize field),
  22.     // so don't copy too much or we risk a fault if the structure is located on the end of a page.
  23.     // All other non-PCM wave formats share the WAVEFORMATEX base structure
  24.     // Note: I don't keep around anything after the cbSize of the WAVEFORMATEX struct so that I don't need to
  25.     // worry about allocating additional space. If we need to keep this info around in the future, we can either
  26.     // allocate it dynamically here, or keep the information in any derived format-specific classes.
  27.     DWORD dwSize;
  28.     WAVEFORMATEX *pwfx = lpWOD->lpFormat;
  29.     if (pwfx->wFormatTag == WAVE_FORMAT_PCM)
  30.     {
  31.         dwSize = sizeof(PCMWAVEFORMAT);
  32.         m_WaveFormat.cbSize = 0;
  33.     }
  34.     else
  35.     {
  36.         dwSize = sizeof(WAVEFORMATEX);
  37.     }
  38.     memcpy(&m_WaveFormat,pwfx,dwSize);
  39.     m_lpWaveHdrHead    = NULL;
  40.     m_lpWaveHdrTail    = NULL;
  41.     m_lpWaveHdrCurrent = NULL;
  42.     m_lpCurrData       = NULL;
  43.     m_lpCurrDataEnd    = NULL;
  44.     m_dwByteCount      = 0;
  45.     m_dwLoopCount = 0;
  46.     m_SecondaryGainClass=0;
  47.     SetGain(pDeviceContext->GetDefaultStreamGain()); // Set gain to default value
  48.     // DEBUGMSG(1, (TEXT("Opening stream 0x%xrn"),this));
  49.     // Add stream to list. This will start playback.
  50.     pDeviceContext->NewStream(this);
  51.     DoCallbackStreamOpened();
  52.     return S_OK;
  53. }
  54. DWORD StreamContext::Close()
  55. {
  56.     if (StillPlaying())
  57.     {
  58.         return WAVERR_STILLPLAYING;
  59.     }
  60.     // Be sure to turn off speaker if we turned it on.
  61.     ForceSpeaker(FALSE);
  62.     // DEBUGMSG(1, (TEXT("Closing stream 0x%xrn"),this));
  63.     DoCallbackStreamClosed();
  64.     return MMSYSERR_NOERROR;
  65. }
  66. // Assumes lock is taken
  67. LONG StreamContext::AddRef()
  68. {
  69.     LONG RefCount = ++m_RefCount;
  70. //    DEBUGMSG(1, (TEXT("AddRef stream 0x%x, RefCount=%drn"),this,RefCount));
  71.     return RefCount;
  72. }
  73. // Assumes lock is taken
  74. LONG StreamContext::Release()
  75. {
  76.     LONG RefCount = --m_RefCount;
  77. //    DEBUGMSG(1, (TEXT("Releasing stream 0x%x, RefCount=%drn"),this,RefCount));
  78.     if (RefCount==0)
  79.     {
  80.         // DEBUGMSG(1, (TEXT("Deleting stream 0x%xrn"),this));
  81.         // Only remove stream from list when all refcounts are gone.
  82.         m_pDeviceContext->DeleteStream(this);
  83.         delete this;
  84.     }
  85.     return RefCount;
  86. }
  87. DWORD StreamContext::QueueBuffer(LPWAVEHDR lpWaveHdr)
  88. {
  89.     if (!(lpWaveHdr->dwFlags & WHDR_PREPARED))
  90.     {
  91.         return WAVERR_UNPREPARED;
  92.     }
  93.     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
  94.     lpWaveHdr->dwFlags &= ~WHDR_DONE;
  95.     lpWaveHdr->lpNext=NULL;
  96.     lpWaveHdr->dwBytesRecorded=0;
  97.     if (!m_lpWaveHdrHead)
  98.     {
  99.         m_lpWaveHdrHead = lpWaveHdr;
  100.     }
  101.     else
  102.     {
  103.         m_lpWaveHdrTail->lpNext=lpWaveHdr;
  104.     }
  105.     m_lpWaveHdrTail=lpWaveHdr;
  106.     // Note: Even if head & tail are valid, current may be NULL if we're in the middle of
  107.     // a loop and ran out of data. So, we need to check specifically against current to
  108.     // decide if we need to initialize it.
  109.     if (!m_lpWaveHdrCurrent)
  110.     {
  111.         m_lpWaveHdrCurrent = lpWaveHdr;
  112.         m_lpCurrData    = (PBYTE)lpWaveHdr->lpData;
  113.         m_lpCurrDataEnd = (PBYTE)lpWaveHdr->lpData + lpWaveHdr->dwBufferLength;
  114.         if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)    // if this is the start of a loop block
  115.         {
  116.             m_dwLoopCount = lpWaveHdr->dwLoops;     // save # of loops
  117.         }
  118.     }
  119.     if (m_bRunning)
  120.     {
  121.         m_pDeviceContext->StreamReadyToRender(this);
  122.     }
  123.     return MMSYSERR_NOERROR;
  124. }
  125. // Note: I've found that when we return used buffers, the wave manager may
  126. // call back into the wave driver in the same thread context to close the stream when
  127. // we return the last buffer.
  128. // If it wasn't the last buffer, the close call will return MMSYSERR_STILLPLAYING.
  129. // However, if it was the last buffer, the close will proceed, and the
  130. // stream may be deleted out from under us. Note that a Lock won't help us here,
  131. // since we're in the same thread which already owns the lock.
  132. // The solution to this is the AddRef/Release use on the stream context, which keeps it
  133. // around if we're acessing it, even if it's closed.
  134. // Assumes lock is taken
  135. PBYTE StreamContext::GetNextBuffer()
  136. {
  137.     LPWAVEHDR lpOldHdr;
  138.     LPWAVEHDR lpNewHdr;
  139.     LPSTR pNewBuf=NULL;
  140.     // Get a pointer to the current buffer which is now done being processed
  141.     lpOldHdr=m_lpWaveHdrCurrent;
  142.     if (!lpOldHdr)
  143.     {
  144.         return NULL;
  145.     }
  146.     // Are we in a loop
  147.     // Note: a loopcount of 1 means we're not really in a loop
  148.     if (m_dwLoopCount>1)
  149.     {
  150.         // We're in a loop!
  151.         if (lpOldHdr->dwFlags & WHDR_ENDLOOP)
  152.         {
  153.            // In loop, last buffer
  154.             // If dwLoopCount was set to INFINITE, loop forever
  155.             // (Note: this is not explicitly in the wave driver API spec)
  156.             if (m_dwLoopCount!=INFINITE)
  157.             {
  158.            m_dwLoopCount--;                    // decrement loop count
  159.             }
  160.            lpNewHdr=m_lpWaveHdrHead;           // go back to start of loop
  161.         }
  162.         else
  163.         {
  164.            // In loop, intermediate buffer
  165.            lpNewHdr=lpOldHdr->lpNext;          // just go to next buffer in loop block
  166.         }
  167.         lpOldHdr=NULL;
  168.     }
  169.     else
  170.     {
  171.         // Not in a loop; return old buffer and get new buffer
  172.         lpNewHdr=lpOldHdr->lpNext;
  173.         m_lpWaveHdrHead = lpNewHdr;           // reset list head
  174.         if (!lpNewHdr)
  175.         {
  176.             m_lpWaveHdrTail=NULL;             // no new buffer, reset tail to NULL
  177.         }
  178.         else if (lpNewHdr->dwFlags & WHDR_BEGINLOOP)    // if new buffer is start of a loop block
  179.         {
  180.             m_dwLoopCount=lpNewHdr->dwLoops;  // save # of loops
  181.         }
  182.     }
  183.     m_lpWaveHdrCurrent=lpNewHdr;              // save current buffer pointer
  184.     if (lpNewHdr)
  185.     {
  186.         m_lpCurrData    = (PBYTE)lpNewHdr->lpData;  // reinitialize data pointer
  187.         m_lpCurrDataEnd = m_lpCurrData + lpNewHdr->dwBufferLength;
  188.     }
  189.     else
  190.     {
  191.         m_lpCurrData  = NULL;
  192.         m_lpCurrDataEnd = NULL;
  193.     }
  194.     // Return the old buffer
  195.     // This may cause the stream to be destroyed, so make sure that any calls to this function
  196.     // are within an AddRef/Release block
  197.     if (lpOldHdr)
  198.     {
  199.         ReturnBuffer(lpOldHdr);
  200.     }
  201.     return m_lpCurrData;
  202. }
  203. DWORD StreamContext::BreakLoop()
  204. {
  205.     AddRef();
  206.     if (m_dwLoopCount>0)
  207.     {
  208.         m_dwLoopCount = 0;
  209.         LPWAVEHDR lpHdr;
  210.         while (m_lpWaveHdrHead!=m_lpWaveHdrCurrent)
  211.         {
  212.             lpHdr = m_lpWaveHdrHead;
  213.             m_lpWaveHdrHead = lpHdr->lpNext;
  214.             if (m_lpWaveHdrHead==NULL)
  215.             {
  216.                 m_lpWaveHdrTail=NULL;
  217.             }
  218.             ReturnBuffer(lpHdr);
  219.         }
  220.     }
  221.     Release();
  222.     return MMSYSERR_NOERROR;
  223. }
  224. // Gain table
  225. // Calculated as: 0x10000 * exp(dBGain/20), for dBGain from 0 to -63
  226. // Sample code to generate using VC++
  227. //
  228. //    #include "stdafx.h"
  229. //    #include "math.h"
  230. //
  231. //    const int NumEntries = 64;
  232. //    const double fdBMin = -100;
  233. //
  234. //    int main(int argc, char* argv[])
  235. //    {
  236. //      const double fNumEntries = ((double)(NumEntries-1));
  237. //      for (int i=0;i<NumEntries;i++)
  238. //      {
  239. //          double fVol = fdBMin * ((double)(i)) / fNumEntries;
  240. //          double fMulVal = exp(fVol/20);
  241. //          unsigned long MulVal = (unsigned long)(fMulVal * (double)0x10000);
  242. //          printf("0x%04x, // %d: %f dBn",MulVal,i,fVol);
  243. //      }
  244. //      return 0;
  245. //    }
  246. //
  247. const DWORD GainMap[] =
  248. {
  249. 0x10000, // 0: 0.000000 dB
  250. 0xec77, // 1: -1.587302 dB
  251. 0xda6d, // 2: -3.174603 dB
  252. 0xc9c2, // 3: -4.761905 dB
  253. 0xba5d, // 4: -6.349206 dB
  254. 0xac25, // 5: -7.936508 dB
  255. 0x9f03, // 6: -9.523810 dB
  256. 0x92e1, // 7: -11.111111 dB
  257. 0x87ac, // 8: -12.698413 dB
  258. 0x7d52, // 9: -14.285714 dB
  259. 0x73c2, // 10: -15.873016 dB
  260. 0x6aed, // 11: -17.460317 dB
  261. 0x62c5, // 12: -19.047619 dB
  262. 0x5b3b, // 13: -20.634921 dB
  263. 0x5445, // 14: -22.222222 dB
  264. 0x4dd7, // 15: -23.809524 dB
  265. 0x47e7, // 16: -25.396825 dB
  266. 0x426b, // 17: -26.984127 dB
  267. 0x3d59, // 18: -28.571429 dB
  268. 0x38ab, // 19: -30.158730 dB
  269. 0x3458, // 20: -31.746032 dB
  270. 0x305a, // 21: -33.333333 dB
  271. 0x2ca9, // 22: -34.920635 dB
  272. 0x2941, // 23: -36.507937 dB
  273. 0x261b, // 24: -38.095238 dB
  274. 0x2333, // 25: -39.682540 dB
  275. 0x2083, // 26: -41.269841 dB
  276. 0x1e08, // 27: -42.857143 dB
  277. 0x1bbe, // 28: -44.444444 dB
  278. 0x19a0, // 29: -46.031746 dB
  279. 0x17ab, // 30: -47.619048 dB
  280. 0x15dd, // 31: -49.206349 dB
  281. 0x1432, // 32: -50.793651 dB
  282. 0x12a7, // 33: -52.380952 dB
  283. 0x113b, // 34: -53.968254 dB
  284. 0x0fea, // 35: -55.555556 dB
  285. 0x0eb3, // 36: -57.142857 dB
  286. 0x0d94, // 37: -58.730159 dB
  287. 0x0c8b, // 38: -60.317460 dB
  288. 0x0b96, // 39: -61.904762 dB
  289. 0x0ab4, // 40: -63.492063 dB
  290. 0x09e3, // 41: -65.079365 dB
  291. 0x0921, // 42: -66.666667 dB
  292. 0x086f, // 43: -68.253968 dB
  293. 0x07ca, // 44: -69.841270 dB
  294. 0x0732, // 45: -71.428571 dB
  295. 0x06a6, // 46: -73.015873 dB
  296. 0x0624, // 47: -74.603175 dB
  297. 0x05ac, // 48: -76.190476 dB
  298. 0x053d, // 49: -77.777778 dB
  299. 0x04d7, // 50: -79.365079 dB
  300. 0x0478, // 51: -80.952381 dB
  301. 0x0421, // 52: -82.539683 dB
  302. 0x03d0, // 53: -84.126984 dB
  303. 0x0386, // 54: -85.714286 dB
  304. 0x0341, // 55: -87.301587 dB
  305. 0x0301, // 56: -88.888889 dB
  306. 0x02c6, // 57: -90.476190 dB
  307. 0x0290, // 58: -92.063492 dB
  308. 0x025e, // 59: -93.650794 dB
  309. 0x0230, // 60: -95.238095 dB
  310. 0x0205, // 61: -96.825397 dB
  311. 0x01de, // 62: -98.412698 dB
  312. 0x01b9, // 63: -100.000000 dB
  313. };
  314. DWORD StreamContext::MapGain(DWORD Gain)
  315. {
  316.     DWORD TotalGain = Gain & 0xFFFF;
  317.     DWORD SecondaryGain = m_pDeviceContext->GetSecondaryGainLimit(m_SecondaryGainClass) & 0xFFFF;
  318.     if (m_SecondaryGainClass < SECONDARYDEVICEGAINCLASSMAX)
  319.     {
  320.         // Apply device gain
  321.         DWORD DeviceGain = m_pDeviceContext->GetGain() & 0xFFFF;
  322.         TotalGain *= DeviceGain;
  323.         TotalGain += 0xFFFF;  // Round up
  324.         TotalGain >>= 16;     // Shift to lowest 16 bits
  325.     }
  326.     // Apply secondary gain
  327.     TotalGain *= SecondaryGain;
  328.     TotalGain += 0xFFFF;  // Round up
  329.     TotalGain >>= 16;     // Shift to lowest 16 bits
  330.     // Special case 0 as totally muted
  331.     if (TotalGain==0)
  332.     {
  333.         return 0;
  334.     }
  335.     // Convert to index into table
  336.     DWORD Index = 63 - (TotalGain>>10);
  337.     return GainMap[Index];
  338. }
  339. DWORD StreamContext::GetPos(PMMTIME pmmt)
  340. {
  341.     switch (pmmt->wType)
  342.     {
  343.     case TIME_SAMPLES:
  344.         pmmt->u.sample = (m_dwByteCount * 8) /
  345.                          (m_WaveFormat.nChannels * m_WaveFormat.wBitsPerSample);
  346.         break;
  347.     case TIME_MS:
  348.         if (m_WaveFormat.nAvgBytesPerSec != 0)
  349.         {
  350.             pmmt->u.ms = (m_dwByteCount * 1000) / m_WaveFormat.nAvgBytesPerSec;
  351.             break;
  352.         }
  353.         // If we don't know avg bytes per sec, fall through to TIME_BYTES
  354.     default:
  355.         // Anything else, return TIME_BYTES instead.
  356.         pmmt->wType = TIME_BYTES;
  357.         // Fall through to TIME_BYTES
  358.     case TIME_BYTES:
  359.         pmmt->u.cb = m_dwByteCount;
  360.     }
  361.     return MMSYSERR_NOERROR;
  362. }
  363. HRESULT WaveStreamContext::Open(DeviceContext *pDeviceContext, LPWAVEOPENDESC lpWOD, DWORD dwFlags)
  364. {
  365.     HRESULT Result;
  366.     Result = StreamContext::Open(pDeviceContext,lpWOD,dwFlags);
  367.     if (FAILED(Result))
  368.     {
  369.         return Result;
  370.     }
  371.     if (m_WaveFormat.wBitsPerSample == 8)
  372.     {
  373.         if (m_WaveFormat.nChannels == 1)
  374.         {
  375.             m_SampleType = PCM_TYPE_M8;
  376.             m_SampleSize = 1;
  377.         }
  378.         else
  379.         {
  380.             m_SampleType = PCM_TYPE_S8;
  381.             m_SampleSize = 2;
  382.         }
  383.     }
  384.     else
  385.     {
  386.         if (m_WaveFormat.nChannels == 1)
  387.         {
  388.             m_SampleType = PCM_TYPE_M16;
  389.             m_SampleSize = 2;
  390.         }
  391.         else
  392.         {
  393.             m_SampleType = PCM_TYPE_S16;
  394.             m_SampleSize = 4;
  395.         }
  396.     }
  397.     SetRate(0x10000);
  398.     int i;
  399.     for (i=0;i<OUTCHANNELS;i++)
  400.     {
  401.         m_PrevSamp[i] = 0;
  402.         m_CurrSamp[i] = 0;
  403.     }
  404.     m_CurrT    = 0x200;   // Initializing to this ensures we get the 1st sample.
  405.     return S_OK;
  406. }
  407. DWORD WaveStreamContext::GetRate(DWORD *pdwMultiplier)
  408. {
  409.     *pdwMultiplier = m_dwMultiplier;
  410.     return MMSYSERR_NOERROR;
  411. }
  412. DWORD StreamContext::Run()
  413. {
  414.     m_bRunning=TRUE;
  415.     if (m_lpCurrData)
  416.     {
  417.         m_pDeviceContext->StreamReadyToRender(this);
  418.     }
  419.     return MMSYSERR_NOERROR;
  420. }
  421. DWORD StreamContext::Stop()
  422. {
  423.     m_bRunning=FALSE;
  424.     return MMSYSERR_NOERROR;
  425. }
  426. DWORD StreamContext::Reset()
  427. {
  428.     AddRef();
  429.     // Stop stream for now.
  430.     Stop();
  431.     m_lpWaveHdrCurrent  = NULL;
  432.     m_lpCurrData       = NULL;
  433.     m_lpCurrDataEnd    = NULL;
  434.     m_dwByteCount      = 0;
  435.     m_dwLoopCount      = 0;
  436.     LPWAVEHDR lpHdr;
  437.     while (m_lpWaveHdrHead)
  438.     {
  439.         lpHdr = m_lpWaveHdrHead;
  440.         m_lpWaveHdrHead = lpHdr->lpNext;
  441.         if (m_lpWaveHdrHead==NULL)
  442.         {
  443.             m_lpWaveHdrTail=NULL;
  444.         }
  445.         ReturnBuffer(lpHdr);
  446.     }
  447.     Release();
  448.     return MMSYSERR_NOERROR;
  449. }
  450. DWORD StreamContext::ForceSpeaker (BOOL bForceSpeaker)
  451. {
  452.     // Normalize to 0 or 1
  453.     bForceSpeaker = (bForceSpeaker!=0);
  454.     if (bForceSpeaker==m_bForceSpeaker)
  455.     {
  456.         return MMSYSERR_NOERROR;
  457.     }
  458.     m_bForceSpeaker = bForceSpeaker;
  459.     return g_pHWContext->ForceSpeaker(bForceSpeaker);
  460. }