⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wavethread.cpp

📁 ppciaxclient softphone
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// CWaveInThread.cpp : implementation file
//


#include "stdafx.h"
#include "WaveThread.h"


/////////////////////////////////////////////////////////////////////////////
// CWaveInThread thread

CWaveInThread::CWaveInThread()
{
   m_pcbWaveIn                = NULL;
   m_bInitialized             = FALSE;
   m_threadId                 = 0;
   m_thread                   = NULL;
   m_hWaveIn                  = NULL;
   m_pWaveInBuffer            = NULL;
   m_pWaveCopyBuffer          = NULL;
   m_pWaveHeaderArray         = NULL;
   m_dwActiveThreadPriority   = THREAD_PRIORITY_NORMAL;
   m_wBufferCount             = 0;
   m_dwSingleBufferSize         = 0;
   m_dwBufferSize             = 0;
   m_dwCopyBufferBytes        = 0;
   m_pCopyBufferPos           = NULL;
   m_bPause                   = FALSE;

   ZeroMemory(&m_wfx, sizeof(m_wfx));

   InitializeCriticalSection(&m_critSecRtp);

   m_hEventKill = CreateEvent(NULL, FALSE, FALSE, NULL);
}


CWaveInThread::~CWaveInThread()
{
   // Stop the thread processing
   StopThread();

   // Delete the critical section
	DeleteCriticalSection(&m_critSecRtp);

   // Destroy events
   CloseHandle(m_hEventKill);
}


// Capture initialization
BOOL CWaveInThread::Init(cbWaveIn pcbWaveIn,             // Callback function for event notifications, NULL = No callback!
                         DWORD dwActiveThreadPriority,   // Thread Priority for this thread, if capturing is active
                         WORD wBufferCount,              // Count of buffers to use
                         DWORD dwSingleBufferSize,       // Size of a single buffer in bytes (eg. 8000Hz Mono 16bit: 10ms = 160bytes)
                         WORD wChannels,                 // Mono = 1; Stereo = 2
                         DWORD dwSamplesPerSec,          // 8000Hz/11025Hz/22050Hz/44100Hz
                         WORD wBitsPerSample)            // 8bit/16bit
{
   if (
       ( m_bInitialized
       ) ||
       ( dwActiveThreadPriority > THREAD_PRIORITY_IDLE
       ) ||
       ( wBufferCount < INTERNAL_WAVEOUT_BUFFER_COUNT
       ) ||
       ( dwSingleBufferSize < 80
       ) ||
       ( wChannels < 1
       ) ||
       ( wChannels > 2
       ) ||
       ( 
        ( wBitsPerSample != 8
        ) && 
        ( wBitsPerSample != 16
        )
       ) ||
       ( 
        ( dwSamplesPerSec != 8000
        ) && 
        ( dwSamplesPerSec != 11025
        ) && 
        ( dwSamplesPerSec != 22050  
        ) && 
        ( dwSamplesPerSec != 44100
        )
       )
      )
   {
      return FALSE;
   }

   m_pcbWaveIn                = pcbWaveIn;
   m_dwActiveThreadPriority   = dwActiveThreadPriority;
   m_wBufferCount             = wBufferCount;
   m_dwSingleBufferSize       = dwSingleBufferSize;

   m_wfx.cbSize               = 0;
   m_wfx.wFormatTag           = WAVE_FORMAT_PCM;
   m_wfx.nChannels            = wChannels;
   m_wfx.nSamplesPerSec       = dwSamplesPerSec;
   m_wfx.nBlockAlign          = (wBitsPerSample * wChannels) / 8;
   m_wfx.nAvgBytesPerSec      = dwSamplesPerSec * m_wfx.nBlockAlign;
   m_wfx.wBitsPerSample       = wBitsPerSample;

   m_dwBufferSize = wBufferCount * dwSingleBufferSize;

   m_bInitialized = TRUE;

   return TRUE;
}


// Start capturing
BOOL CWaveInThread::StartThread()
{
   UINT           id;
   WORD           i;

   if ((m_thread) || (!m_bInitialized))
   {
      return FALSE;
   }

   // Start the thread
   m_thread = CreateThread(NULL, 
                           0, 
                           ThreadProc, 
                           (void*)this,
                           0, 
                           &m_threadId);

   if (m_thread)
   {
      DWORD dwExitCode;
      
      if (GetExitCodeThread(m_thread, &dwExitCode))
      {
         if (dwExitCode != STILL_ACTIVE)
         {
            return FALSE;
         }
      }

      if (m_hWaveIn == NULL)
      {
         m_pWaveInBuffer = new unsigned char[m_dwBufferSize];

         if (m_pWaveInBuffer)
         {
            ZeroMemory(m_pWaveInBuffer, m_dwBufferSize);

            m_pWaveCopyBuffer = new unsigned char[m_dwBufferSize];

            if (m_pWaveCopyBuffer)
            {
               ZeroMemory(m_pWaveCopyBuffer, m_dwBufferSize);

               m_pWaveHeaderArray = new WAVEHDR[m_wBufferCount];

               if (m_pWaveHeaderArray)
               {
                  ZeroMemory(m_pWaveHeaderArray, m_wBufferCount * sizeof(WAVEHDR));

                  for (id = 0; id < waveInGetNumDevs(); id++) 
                  {
	                  if (waveInOpen(&m_hWaveIn, id, &m_wfx, m_threadId, (DWORD)this, CALLBACK_THREAD) == MMSYSERR_NOERROR) 
                     {
                        for (i=0 ; i<m_wBufferCount ; i++)
                        {
                           m_pWaveHeaderArray[i].dwBufferLength = m_dwSingleBufferSize;
                           m_pWaveHeaderArray[i].lpData = (char*)m_pWaveInBuffer + i * m_dwSingleBufferSize;
                           m_pWaveHeaderArray[i].dwUser = i;

                           waveInPrepareHeader(m_hWaveIn, &m_pWaveHeaderArray[i], sizeof(WAVEHDR));

                           waveInAddBuffer(m_hWaveIn, &m_pWaveHeaderArray[i], sizeof(WAVEHDR));
                        }

                        ResetBuffer();

                        SetThreadPriority(m_thread, m_dwActiveThreadPriority);

                        m_bPause = FALSE;

                        waveInStart(m_hWaveIn);

                        return TRUE;
	                  }
                  }
               }

               delete m_pWaveCopyBuffer;
               m_pWaveCopyBuffer = NULL;
            }

            delete m_pWaveInBuffer;
            m_pWaveInBuffer = NULL;
         }
      }
   }

   StopThread();

   return FALSE;
}


// Stop capturing
BOOL CWaveInThread::StopThread()
{
   WORD i;

   if (m_thread == NULL)
   {
      return FALSE;
   }

   SetThreadPriority(m_thread, THREAD_PRIORITY_NORMAL);

   SetEvent(m_hEventKill);

   if (m_hWaveIn)
   {
      waveInStop(m_hWaveIn);
   }

   // This is ugly, wait for 10 seconds, then kill the thread
   DWORD res = WaitForSingleObject(m_thread, 10000);

   if (res == WAIT_TIMEOUT)
   {
      if (m_thread)
      {
         // OK, do it the hard way
         TerminateThread(m_thread, 0);

         CloseHandle(m_thread);

         m_thread = NULL;
      }
   }

   if (m_hWaveIn)
   {
      waveInReset(m_hWaveIn);

      if (m_pWaveHeaderArray)
      {
         for (i=0 ; i<m_wBufferCount ; i++)
         {
            waveInUnprepareHeader(m_hWaveIn, &m_pWaveHeaderArray[i], sizeof(WAVEHDR));
         }
      }

      waveInClose(m_hWaveIn);
      m_hWaveIn = NULL;
   }

   if (m_pWaveInBuffer)
   {
      delete m_pWaveInBuffer;
      m_pWaveInBuffer = NULL;
   }

   if (m_pWaveCopyBuffer)
   {
      delete m_pWaveCopyBuffer;
      m_pWaveCopyBuffer = NULL;
   }

   if (m_pWaveHeaderArray)
   {
      delete m_pWaveHeaderArray;
      m_pWaveHeaderArray = NULL;
   }

   return TRUE;
}


// Clear the buffer
void CWaveInThread::ResetBuffer()
{
   EnterCriticalSection(&m_critSecRtp);

   m_pCopyBufferPos = NULL;

   if (m_bPause)
   {
      SetThreadPriority(m_thread, m_dwActiveThreadPriority);

      waveInStart(m_hWaveIn);

      m_bPause = FALSE;
   }

   LeaveCriticalSection(&m_critSecRtp);
}


// Get the size of the needed buffer for one second of data
DWORD CWaveInThread::GetBytesPerSecond()
{
   if (m_bInitialized)
   {
      return m_wfx.nAvgBytesPerSec;
   }

   return 0;
}


// Get the current length of data in the buffer
DWORD CWaveInThread::GetDataLen()
{
   DWORD dwBytes;
   
   EnterCriticalSection(&m_critSecRtp);

   dwBytes = m_dwCopyBufferBytes;
   
   LeaveCriticalSection(&m_critSecRtp);

   return dwBytes;
}


// Get captured data
BOOL CWaveInThread::ReadData(unsigned char* pBuffer, // Data will be copied into the buffer
                             DWORD dwCount)          // Count of bytes to copy
{
   EnterCriticalSection(&m_critSecRtp);

   if (
       ( pBuffer == NULL
       ) ||
       ( m_pCopyBufferPos == NULL
       ) || 
       ( m_dwCopyBufferBytes < dwCount
       )
      )
   {
      LeaveCriticalSection(&m_critSecRtp);

      return FALSE;
   }

   if (m_pCopyBufferPos + dwCount > m_pWaveCopyBuffer + m_dwBufferSize)
   {
      memcpy(pBuffer, 
             m_pCopyBufferPos, 
             m_pWaveCopyBuffer + m_dwBufferSize - m_pCopyBufferPos);
      pBuffer += m_pWaveCopyBuffer + m_dwBufferSize - m_pCopyBufferPos;
      memcpy(pBuffer, 
             m_pWaveCopyBuffer, 
             m_pCopyBufferPos + dwCount - (m_pWaveCopyBuffer + m_dwBufferSize));
      m_pCopyBufferPos = m_pWaveCopyBuffer + ((m_pCopyBufferPos + dwCount) - (m_pWaveCopyBuffer + m_dwBufferSize));
   }
   else
   {
      memcpy(pBuffer, m_pCopyBufferPos, dwCount);
      m_pCopyBufferPos += dwCount;
   }

   m_dwCopyBufferBytes -= dwCount;

   if ((m_bPause) && (m_dwCopyBufferBytes + (m_dwBufferSize / m_wBufferCount) <= m_dwBufferSize))
   {
      SetThreadPriority(m_thread, m_dwActiveThreadPriority);

      waveInStart(m_hWaveIn);

      m_bPause = FALSE;
   }

   LeaveCriticalSection(&m_critSecRtp);

   return TRUE;
}


// Handles MM-API for capturing
DWORD WINAPI CWaveInThread::ThreadProc(LPVOID lpParameter)
{
   CWaveInThread* pWaveIn     = (CWaveInThread*)lpParameter;
   MSG            msg;
   DWORD          dwWait      = 0;
   DWORD          dwUser      = 0;
   WAVEHDR        *pWaveHdr   = NULL;
   WAVE_IN_EVENT  event;

   if (pWaveIn == NULL)
   {
      return -1;
   }

	while ((dwWait = WaitForSingleObject(pWaveIn->m_hEventKill, 5)) != 0)
   {
      // Handle MMAPI wave capturing thread messages
      while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
      {
         switch (msg.message)
         {
            case MM_WIM_DATA:
         	   EnterCriticalSection(&pWaveIn->m_critSecRtp);

               event = WAVE_IN_EVENT_NONE;

               pWaveHdr = (WAVEHDR*)msg.lParam;

               // Unprepare header, initialize with the next buffer position, prepare the header 
               //  again and add it to the wave capture device.
               if (pWaveHdr)
               {
                  waveInUnprepareHeader(pWaveIn->m_hWaveIn, pWaveHdr, sizeof(WAVEHDR));

                  dwUser = pWaveHdr->dwUser;

                  if (pWaveIn->m_pCopyBufferPos == 0)
                  {
                     pWaveIn->m_pCopyBufferPos = pWaveIn->m_pWaveCopyBuffer + dwUser * pWaveHdr->dwBufferLength;
                     pWaveIn->m_dwCopyBufferBytes = 0;
                  }

                  if (pWaveIn->m_dwCopyBufferBytes + pWaveHdr->dwBufferLength <= pWaveIn->m_dwBufferSize)
                  {
                     memcpy((char*)pWaveIn->m_pWaveCopyBuffer + dwUser * pWaveHdr->dwBufferLength, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded);

                     if (pWaveHdr->dwBytesRecorded != pWaveHdr->dwBufferLength)
                     {
                        ZeroMemory(pWaveHdr->lpData + pWaveHdr->dwBytesRecorded, pWaveHdr->dwBufferLength - pWaveHdr->dwBytesRecorded);
                     }

                     pWaveIn->m_dwCopyBufferBytes += pWaveHdr->dwBufferLength;

                     event = WAVE_IN_EVENT_NEW_BUFFER;
                  }
                  else
                  {
                     SetThreadPriority(pWaveIn->m_thread, THREAD_PRIORITY_NORMAL);

                     waveInStop(pWaveIn->m_hWaveIn);

                     pWaveIn->m_bPause = TRUE;

                     event = WAVE_IN_EVENT_BUFFER_FULL;
                  }

                  ZeroMemory(pWaveHdr, sizeof(WAVEHDR));

                  pWaveHdr->dwBufferLength = pWaveIn->m_dwSingleBufferSize;
                  pWaveHdr->lpData = (char*)pWaveIn->m_pWaveInBuffer + dwUser * pWaveIn->m_dwSingleBufferSize;
                  pWaveHdr->dwUser = dwUser;

                  waveInPrepareHeader(pWaveIn->m_hWaveIn, pWaveHdr, sizeof(WAVEHDR));

                  waveInAddBuffer(pWaveIn->m_hWaveIn, pWaveHdr, sizeof(WAVEHDR));
               }

         	   LeaveCriticalSection(&pWaveIn->m_critSecRtp);

               if ((pWaveIn->m_pcbWaveIn != NULL) && (event != WAVE_IN_EVENT_NONE))
               {
                  (pWaveIn->m_pcbWaveIn)(event);
               }
               break;
            default:
               break;
         }
      }
   }

   CloseHandle(pWaveIn->m_thread);
   pWaveIn->m_thread = NULL;

   return 0;
}


/////////////////////////////////////////////////////////////////////////////
// CWaveOutThread thread

CWaveOutThread::CWaveOutThread()
{
   m_pcbWaveOut               = NULL;
   m_bInitialized             = FALSE;
   m_threadId                 = 0;
   m_thread                   = NULL;
   m_hWaveOut                 = NULL;
   m_pWaveOutBuffer           = NULL;
   m_pWaveCopyBuffer          = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -