< WaveBuffer.h >
 #ifndef __WAVE_BUFFER_H__  
 #define __WAVE_BUFFER_H__  
   
 #include <windows.h>  
 #include <MMSystem.h>  
   
 #include "BufferQueue.h"  
   
 class WaveBuffer {  
 public:  
      WAVEHDR*     pWaveHdr;  
      int               length;  
      bool          bDeleteData;  
   
      WaveBuffer(WAVEHDR *hdr, int len, bool deleteData = true) {  
           pWaveHdr = hdr;  
           length = len;  
           bDeleteData = deleteData;  
      }  
   
      virtual ~WaveBuffer() {  
           if (pWaveHdr && bDeleteData) {  
                delete[] pWaveHdr->lpData;  
                delete pWaveHdr;  
           }  
      }  
 };  
   
 class WaveBufferQueue {  
 public:  
      WaveBufferQueue(bool deleteData = true);  
      virtual ~WaveBufferQueue();  
   
      int push_back(WAVEHDR *pWaveHdr);  
      WaveBuffer* pop_front();  
   
      void clear() { m_pWaveQue->clear(); }  
      int count() { return m_pWaveQue->count(); }  
   
 private:  
      BufferQueue<WaveBuffer>     *m_pWaveQue;  
      int          m_nCount;  
      bool     m_bDeleteData;  
 };  
   
   
 #endif  
   
BufferQueue 템플릿 클래스는 C++ double linked-list Template Queue 포스트 참조< WaveBuffer.cpp >
 #include "WaveBuffer.h"  
   
   
 WaveBufferQueue::WaveBufferQueue(bool deleteData)  
 {  
      m_pWaveQue = new BufferQueue<WaveBuffer>(0);     // 무제한 버퍼  
      m_bDeleteData = deleteData;  
 }  
   
 WaveBufferQueue::~WaveBufferQueue()  
 {  
      if (m_pWaveQue) {  
           delete m_pWaveQue;  
           m_pWaveQue = NULL;  
      }  
 }  
   
 int WaveBufferQueue::push_back(WAVEHDR *pWaveHdr)  
 {  
      WaveBuffer *wave = new WaveBuffer(pWaveHdr, pWaveHdr->dwBufferLength, m_bDeleteData);  
      return m_pWaveQue->push_back(wave);  
 }  
   
 WaveBuffer* WaveBufferQueue::pop_front()  
 {  
      return m_pWaveQue->pop_front();  
 }  
   
< WaveIn.h >
 #ifndef __WAVE_IN_H__  
 #define __WAVE_IN_H__  
   
 #include <windows.h>  
 #include <MMSystem.h>  
   
 #include "WaveBuffer.h"  
   
 class WaveIn  
 {  
 public:  
      WaveIn();  
      virtual ~WaveIn();  
   
      /* WaveIn API */  
      int open(WAVEFORMATEX waveInFormat, int buff_count, double duration);  
      void close();  
      void setWaveInFunc(void (*func)(WAVEHDR *pHdr, void *pData), void *pData)   
      {   
           waveInHandlerFunc = func;   
           m_pWaveInHandlerData = pData;   
      }  
   
 public:  
      void processWaveInDone(WAVEHDR *pHdr);  
      void processWaveInClose();  
      void running();       
   
 protected:  
      HWAVEIN          m_hWaveIn;  
      HANDLE          m_hWaveInThread;  
      BOOL          m_bWaveInRun;  
      WAVEHDR*     m_pWaveInHdr;  
      int               m_nWaveInHdrCount;  
   
      int                         m_nWaveInHdrPrepareCount;  
      WaveBufferQueue*     m_pWaveBufferQue;  
   
      WAVEFORMATEX     m_waveInFormatEx;  
   
      void (*waveInHandlerFunc)(WAVEHDR *pHdr, void *pData);  
      void *m_pWaveInHandlerData;  
   
      void waveInPrintError(MMRESULT result, LPCTSTR str);  
 };  
   
 #endif  
   
<WaveIn.cpp >
 #include "WaveIn.h"  
 #include "GlobalEnv.h"  
 #include <assert.h>  
 #include <process.h>  
 #include <stdio.h>  
   
 #pragma comment(lib, "winmm.lib")  
   
 WaveIn::WaveIn()  
 {  
      m_hWaveIn = NULL;  
      m_hWaveInThread = NULL;  
      m_bWaveInRun = FALSE;  
   
      memset(&m_waveInFormatEx, 0, sizeof(m_waveInFormatEx));  
      m_pWaveInHdr = NULL;  
      m_nWaveInHdrCount = 0;  
   
      m_pWaveBufferQue = NULL;  
   
      waveInHandlerFunc = NULL;  
      m_pWaveInHandlerData = NULL;  
 }  
   
 WaveIn::~WaveIn()  
 {  
      close();  
 }  
   
 unsigned __stdcall Thread_WaveIn(LPVOID lpParam)  
 {  
      WaveIn *pWaveIn = (WaveIn *)lpParam;  
      pWaveIn->running();  
      return 0;  
 }  
   
 void WaveIn::running()  
 {  
      MMRESULT mRes;  
      WAVEHDR *pHdr;  
      WaveBuffer *pWave;  
   
      while (1)  
      {  
           pWave = m_pWaveBufferQue->pop_front();  
           if (pWave == NULL)  
           {  
                Sleep(1);  
                continue;  
           }  
   
           pHdr = pWave->pWaveHdr;  
   
           mRes = waveInUnprepareHeader(m_hWaveIn, pHdr, sizeof(WAVEHDR));  
           if (mRes != MMSYSERR_NOERROR) {  
                waveInPrintError(mRes, "waveInUnprepareHeader");  
                assert(FALSE);  
                continue;  
           }  
           m_nWaveInHdrPrepareCount--;  
   
           if (waveInHandlerFunc)  
                waveInHandlerFunc(pHdr, m_pWaveInHandlerData);  
   
           delete pWave;  
   
           if (m_bWaveInRun)  
           {  
                mRes = waveInPrepareHeader(m_hWaveIn, pHdr, sizeof(WAVEHDR));  
                if (mRes != MMSYSERR_NOERROR) {  
                     waveInPrintError(mRes, "waveInPrepareHeader");  
                     assert(FALSE);  
                     continue;  
                }  
   
                mRes = waveInAddBuffer(m_hWaveIn, pHdr, sizeof(WAVEHDR));  
                if (mRes != MMSYSERR_NOERROR) {  
                     waveInPrintError(mRes, "waveInAddBuffer");  
                     assert(FALSE);  
                     continue;  
                }  
                m_nWaveInHdrPrepareCount++;  
           }  
           else  
           {  
                //DXPRINTF("[%s] WaveIn Hdr Count:%d\n", __FUNCTION__, m_nWaveInHdrPrepareCount);  
                if (m_pWaveBufferQue->count() == 0 && m_nWaveInHdrPrepareCount == 0) {  
                     break;  
                }  
           }  
      }  
 }  
   
 void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)  
 {  
      WaveIn *pWaveIn = (WaveIn *)dwInstance;  
   
      switch(uMsg)  
      {  
      case WIM_OPEN:  
           DXPRINTF("WIM_OPEN\n");  
           break;  
      case WIM_CLOSE:  
           DXPRINTF("WIM_CLOSE\n");  
           pWaveIn->processWaveInClose();  
           break;  
      case WIM_DATA:   
           pWaveIn->processWaveInDone((WAVEHDR *)dwParam1);  
           break;  
      default:  
           break;  
      }  
 }  
   
 void WaveIn::processWaveInDone(WAVEHDR *pHdr)  
 {  
      if (m_pWaveBufferQue)  
           m_pWaveBufferQue->push_back(pHdr);  
 }  
   
 void WaveIn::processWaveInClose()  
 {  
 }  
   
 int WaveIn::open(WAVEFORMATEX waveInFormat, int buff_count, double duration)  
 {  
      MMRESULT mRes;  
   
      if (m_bWaveInRun)  
           return -1;  
   
      memset(&m_waveInFormatEx, 0, sizeof(m_waveInFormatEx));  
      m_waveInFormatEx.wFormatTag = WAVE_FORMAT_PCM;  
      m_waveInFormatEx.nChannels = waveInFormat.nChannels;  
      m_waveInFormatEx.nSamplesPerSec = waveInFormat.nSamplesPerSec;  
      m_waveInFormatEx.wBitsPerSample = waveInFormat.wBitsPerSample;  
      m_waveInFormatEx.nBlockAlign = m_waveInFormatEx.nChannels*m_waveInFormatEx.wBitsPerSample/8;  
      m_waveInFormatEx.nAvgBytesPerSec = m_waveInFormatEx.nSamplesPerSec*m_waveInFormatEx.nBlockAlign;  
      m_waveInFormatEx.cbSize = 0;  
   
      mRes = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &m_waveInFormatEx,   
           (DWORD_PTR)waveInProc, (DWORD_PTR)this, CALLBACK_FUNCTION);  
   
      if (mRes != MMSYSERR_NOERROR) {  
           waveInPrintError(mRes, "waveInOpen");  
           return -2;  
      }  
   
      /* prepare wavein header */  
      int buff_size = (int)(m_waveInFormatEx.nAvgBytesPerSec*duration);  
      buff_size *= m_waveInFormatEx.nChannels;  
   
      m_nWaveInHdrCount = buff_count;  
      m_pWaveInHdr = new WAVEHDR[m_nWaveInHdrCount];  
   
      for (int i=0; i<m_nWaveInHdrCount; i++)  
      {  
           memset(&m_pWaveInHdr[i], 0, sizeof(WAVEHDR));  
           m_pWaveInHdr[i].lpData = new char[buff_size];  
           m_pWaveInHdr[i].dwBufferLength = buff_size;  
           m_pWaveInHdr[i].dwUser = i;  
   
           mRes = waveInPrepareHeader(m_hWaveIn, &m_pWaveInHdr[i], sizeof(WAVEHDR));  
           if (mRes != MMSYSERR_NOERROR) {  
                waveInPrintError(mRes, "waveInPrepareHeader");  
                assert(FALSE);  
                continue;  
           }  
   
           mRes = waveInAddBuffer(m_hWaveIn, &m_pWaveInHdr[i], sizeof(WAVEHDR));  
           if (mRes != MMSYSERR_NOERROR) {  
                waveInPrintError(mRes ,"waveInAddBuffer");  
                assert(FALSE);  
                continue;  
           }  
      }  
   
      m_nWaveInHdrPrepareCount = m_nWaveInHdrCount;  
   
      m_pWaveBufferQue = new WaveBufferQueue(false);  
   
      m_bWaveInRun = TRUE;  
      m_hWaveInThread = (HANDLE)_beginthreadex(NULL, 0, Thread_WaveIn, this, 0, NULL);  
   
      mRes = waveInStart(m_hWaveIn);  
      if (mRes != MMSYSERR_NOERROR) {  
           waveInPrintError(mRes, "waveInStart");  
           return -1;  
      }  
   
      return 0;  
 }  
   
 void WaveIn::close()  
 {  
      MMRESULT mRes;  
   
      if (!m_bWaveInRun || !m_hWaveIn)  
           return;  
   
      m_bWaveInRun = FALSE;  
   
      WaitForSingleObject(m_hWaveInThread, INFINITE);  
   
      mRes = waveInStop(m_hWaveIn);  
      if (mRes != MMSYSERR_NOERROR)  
           waveInPrintError(mRes, "waveInStop");  
   
      for (int i=0; i<m_nWaveInHdrCount; i++)  
           delete[] m_pWaveInHdr[i].lpData;  
      delete m_pWaveInHdr;  
   
      mRes = waveInClose(m_hWaveIn);  
      if (mRes != MMSYSERR_NOERROR)  
           waveInPrintError(mRes ,"waveInClose");  
   
      if (m_pWaveBufferQue) {  
           delete m_pWaveBufferQue;  
           m_pWaveBufferQue = NULL;  
      }  
   
      CloseHandle(m_hWaveInThread);  
 }  
   
 void WaveIn::waveInPrintError(MMRESULT result, LPCTSTR str)  
 {  
      char errmsg[128] = {0};  
      waveInGetErrorText(result, errmsg, sizeof(errmsg));  
      DXPRINTF("%s waveInError: %d %s\n", str, result, errmsg);  
 }  
   
< WaveOut.h >
 #ifndef __WAVE_OUT_H__  
 #define __WAVE_OUT_H__  
   
 #include <windows.h>  
 #include <MMSystem.h>  
 #include <MMReg.h>  
 #include <stdio.h>  
   
 #include "WaveBuffer.h"  
   
 class WaveOut  
 {  
 public:  
      WaveOut();  
      virtual ~WaveOut();  
   
      /* WaveOut API */  
      int open(WAVEFORMATEX waveOutFormat, DWORD channel_layout);  
      void close();  
      int waveOutAdd(unsigned char *buff, int len);  
   
      void setAudioVolume(int val);  
      DWORD getAudioVolume();  
      void reset();  
      void setMaxWaveOutBufferCount(int maxCount) { m_nMaxWaveOutBufferCount = maxCount; }  
        
      int channels() { return m_waveOutFormatEx.Format.nChannels; }  
      int sampleRate() { return m_waveOutFormatEx.Format.nSamplesPerSec; }  
      int channelLayout() { return m_waveOutFormatEx.dwChannelMask; }  
   
 public:  
      void processWaveOutDone(WAVEHDR *pHdr);  
      void processWaveOutClose();  
      void running();  
   
 protected:  
      HWAVEOUT     m_hWaveOut;  
      HANDLE          m_hWaveOutThread;  
      BOOL          m_bWaveOutRun;  
      int               m_nMaxWaveOutBufferCount;  
   
      int                         m_nWaveOutHdrPrepareCount;  
      WaveBufferQueue*     m_pWaveBufferQue;  
   
      DWORD          m_nAudioVolume;  
   
      WAVEFORMATEXTENSIBLE     m_waveOutFormatEx;  
      WAVEOUTCAPS                    m_waveOutCaps;  
   
      void waveOutPrintError(MMRESULT result, LPCTSTR str);  
   
      FILE     *m_pFile;     // audio dump  
 };  
   
 #endif  
   
< WaveOut.cpp >
 #include "WaveOut.h"  
 #include "GlobalEnv.h"  
 #include <assert.h>  
 #include <process.h>  
 #include <stdio.h>  
   
 #pragma comment(lib, "winmm.lib")  
   
 WaveOut::WaveOut()  
 {  
      m_hWaveOut = NULL;  
      m_hWaveOutThread = NULL;  
      m_bWaveOutRun = FALSE;  
   
      m_nWaveOutHdrPrepareCount = 0;  
      m_pWaveBufferQue = new WaveBufferQueue();  
   
      m_nAudioVolume = 0xFFFFFFFF;  
   
      ZeroMemory(&m_waveOutCaps, sizeof(WAVEOUTCAPS));  
      ZeroMemory(&m_waveOutFormatEx, sizeof(WAVEFORMATEXTENSIBLE));  
   
      m_nMaxWaveOutBufferCount = 3;  
   
      m_pFile = NULL;  
 }  
   
 WaveOut::~WaveOut()  
 {  
      close();  
      DX_DELETE_OBJECT(m_pWaveBufferQue);  
 }  
   
 unsigned __stdcall Thread_WaveOut(LPVOID lpParam)  
 {  
      WaveOut *pWaveOut = (WaveOut *)lpParam;  
      pWaveOut->running();  
      return 0;  
 }  
   
 void WaveOut::running()  
 {  
      MMRESULT mRes;  
      WaveBuffer *pWave;  
      WAVEHDR *pHdr;  
   
      while (1)  
      {  
           pWave = m_pWaveBufferQue->pop_front();  
           if (pWave == NULL) {  
                Sleep(1);  
                goto skip;  
           }  
             
           pHdr = pWave->pWaveHdr;  
   
           mRes = waveOutUnprepareHeader(m_hWaveOut, pHdr, sizeof(WAVEHDR));  
           if (mRes != MMSYSERR_NOERROR) {  
                waveOutPrintError(mRes, "waveOutUnprepareHeader");  
                assert(FALSE);  
                continue;  
           }  
   
           delete pWave;  
           InterlockedDecrement((LPLONG)&m_nWaveOutHdrPrepareCount);  
   
 skip:  
           if (!m_bWaveOutRun)  
           {  
                if (m_pWaveBufferQue->count() == 0 && m_nWaveOutHdrPrepareCount == 0) {  
                     break;  
                }  
           }  
      }  
 }  
   
 void WaveOut::processWaveOutDone(WAVEHDR *pHdr)  
 {       
      if (m_pWaveBufferQue) {  
           m_pWaveBufferQue->push_back(pHdr);  
      }  
 }  
   
 void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)  
 {  
      WaveOut *pWaveOut = (WaveOut *)dwInstance;  
   
      switch(uMsg)  
      {  
      case WOM_OPEN:  
           DXPRINTF("WOM_OPEN\n");  
           break;  
      case WOM_CLOSE:  
           DXPRINTF("WOM_CLOSE\n");  
           break;  
      case WOM_DONE:  
           pWaveOut->processWaveOutDone((WAVEHDR *)dwParam1);  
           break;  
      default:  
           break;  
      }  
 }  
   
 int WaveOut::waveOutAdd(unsigned char *buff, int len)  
 {  
      MMRESULT mRes;  
   
      if (!m_bWaveOutRun)  
           return -1;  
   
      //DXPRINTF("wave out buffer count : %d (%d)\n", m_nWaveOutHdrPrepareCount, len);  
      if (m_nMaxWaveOutBufferCount > 0) {  
           if (m_nWaveOutHdrPrepareCount > m_nMaxWaveOutBufferCount) {  
                DXPRINTF("wave out buffer overflow : %d (%d)\n", m_nWaveOutHdrPrepareCount, len);  
                return 0;  
           }  
      }  
   
      WAVEHDR *pHdr = new WAVEHDR;  
      ZeroMemory(pHdr, sizeof(WAVEHDR));  
   
      pHdr->lpData = new char[len];  
      memcpy(pHdr->lpData, buff, len);  
      pHdr->dwBufferLength = len;  
      pHdr->dwFlags = 0;  
   
      mRes = waveOutPrepareHeader(m_hWaveOut, pHdr, sizeof(WAVEHDR));  
      if (mRes != MMSYSERR_NOERROR) {  
           waveOutPrintError(mRes, "waveOutPrepareHeader");  
           delete[] pHdr->lpData;  
           delete pHdr;  
           assert(FALSE);  
           return -2;  
      }  
   
      mRes = waveOutWrite(m_hWaveOut, pHdr, sizeof(WAVEHDR));  
      if (mRes != MMSYSERR_NOERROR) {  
           waveOutPrintError(mRes, "waveOutWrite");  
           delete[] pHdr->lpData;  
           delete pHdr;  
           assert(FALSE);  
           return -3;  
      }  
   
      InterlockedIncrement((LPLONG)&m_nWaveOutHdrPrepareCount);  
   
      if (m_pFile) fwrite(buff, len, 1, m_pFile);  
   
      return 0;  
 }  
   
 int WaveOut::open(WAVEFORMATEX waveOutFormat, DWORD channel_layout)  
 {  
      MMRESULT mRes;  
   
      if (m_bWaveOutRun)  
           return -1;  
   
      m_waveOutFormatEx;  
      memset(&m_waveOutFormatEx, 0, sizeof(WAVEFORMATEXTENSIBLE));  
      m_waveOutFormatEx.Format.wFormatTag = WAVE_FORMAT_PCM;  
      m_waveOutFormatEx.Format.nChannels = waveOutFormat.nChannels;  
      m_waveOutFormatEx.Format.nSamplesPerSec = waveOutFormat.nSamplesPerSec;  
      m_waveOutFormatEx.Format.wBitsPerSample = waveOutFormat.wBitsPerSample;  
      m_waveOutFormatEx.Format.nBlockAlign = waveOutFormat.nChannels*waveOutFormat.wBitsPerSample/8;  
      m_waveOutFormatEx.Format.nAvgBytesPerSec = waveOutFormat.nSamplesPerSec*waveOutFormat.nBlockAlign;  
   
      if (waveOutFormat.nChannels <= 2) {  
           m_waveOutFormatEx.Format.cbSize = 0;  
      } else {  
           m_waveOutFormatEx.dwChannelMask = channel_layout;  
           m_waveOutFormatEx.Samples.wValidBitsPerSample = waveOutFormat.wBitsPerSample;  
           m_waveOutFormatEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;  
           m_waveOutFormatEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;  
           m_waveOutFormatEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);  
      }  
   
      mRes = waveOutOpen(&m_hWaveOut, WAVE_MAPPER, (WAVEFORMATEX *)&m_waveOutFormatEx,  
           (DWORD_PTR)waveOutProc, (DWORD_PTR)this, CALLBACK_FUNCTION);  
   
      if (mRes != MMSYSERR_NOERROR) {  
           waveOutPrintError(mRes, "waveOutOpen");  
           return -2;  
      }  
   
      mRes = waveOutSetVolume(m_hWaveOut, m_nAudioVolume);  
      if (mRes != MMSYSERR_NOERROR) {  
           waveOutPrintError(mRes, "waveOutWrite");  
      }  
   
      m_bWaveOutRun = TRUE;  
      m_hWaveOutThread = (HANDLE)_beginthreadex(NULL, 0, Thread_WaveOut, this, 0, NULL);  
      if (!m_hWaveOutThread) {  
           DXPRINTF("[%s] waveout thread create error, err:%d\n", __FUNCTION__, GetLastError());  
           return -3;  
      }  
   
      ZeroMemory(&m_waveOutCaps, sizeof(WAVEOUTCAPS));  
      mRes = waveOutGetDevCaps((UINT_PTR)m_hWaveOut, &m_waveOutCaps, sizeof(WAVEOUTCAPS));  
      if (mRes != MMSYSERR_NOERROR) {  
           waveOutPrintError(mRes, "waveOutGetDevCaps");  
      }  
   
 #if 0  
      m_pFile = fopen("audio.wav", "wb");  
 #endif  
   
      return 0;  
 }  
   
 void WaveOut::close()  
 {  
      MMRESULT mRes;  
   
      if (!m_bWaveOutRun || !m_hWaveOut)  
           return;  
   
      waveOutReset(m_hWaveOut);  
      m_bWaveOutRun = FALSE;  
   
      WaitForSingleObject(m_hWaveOutThread, INFINITE);  
   
      mRes = waveOutClose(m_hWaveOut);  
      if (mRes != MMSYSERR_NOERROR)  
           waveOutPrintError(mRes, "waveOutClose");  
   
      CloseHandle(m_hWaveOutThread);  
      m_hWaveOutThread = NULL;  
   
      if (m_pFile) {  
           fclose(m_pFile);  
           m_pFile = NULL;  
      }  
 }  
   
 void WaveOut::setAudioVolume(int val)  
 {  
      m_nAudioVolume = val;  
   
      if (m_hWaveOut) {  
           MMRESULT mRes = waveOutSetVolume(m_hWaveOut, m_nAudioVolume);  
           if (mRes != MMSYSERR_NOERROR) {  
                waveOutPrintError(mRes, "waveOutSetVolume");  
           }  
      }  
 }  
   
 DWORD WaveOut::getAudioVolume()  
 {  
      if (m_hWaveOut) {  
           MMRESULT mRes = waveOutGetVolume(m_hWaveOut, &m_nAudioVolume);  
           if (mRes == MMSYSERR_NOERROR) return m_nAudioVolume;  
           waveOutPrintError(mRes, "waveOutGetVolume");  
      }  
      return 0;  
 }  
   
 void WaveOut::reset()  
 {  
      if (m_hWaveOut)  
           waveOutReset(m_hWaveOut);  
 }  
   
 void WaveOut::waveOutPrintError(MMRESULT result, LPCTSTR str)  
 {  
      char errmsg[128] = {0};  
      waveOutGetErrorText(result, errmsg, sizeof(errmsg));  
      DXPRINTF("%s waveOutError: %d %s\n", str, result, errmsg);  
 }  
   
< WaveOut 사용법 >
WaveOut* m_pWaveOut = new WaveOut();
...
// waveout 열기
int open(int channel, int sample_rate, int channel_layout)
{
// open waveout
WAVEFORMATEX waveformat;
memset(&waveformat, 0, sizeof(WAVEFORMATEX));
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = channel;
waveformat.nSamplesPerSec = sample_rate;
waveformat.wBitsPerSample = 16;
waveformat.nBlockAlign = waveformat.nChannels*waveformat.wBitsPerSample/8;
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec*waveformat.nBlockAlign;
waveformat.cbSize = 0;
int ret = m_pWaveOut->open(waveformat, channel_layout);
if (ret < 0) m_pWaveOut->close();
return ret;
}
// waveout 출력 - buff : 오디오 pcm 데이터, size : 오디오 pcm 데이터 사이즈
int waveout(unsigned char *buff, int size)
{
return m_pWaveOut->waveOutAdd(buff, size);
}
// waveout 닫기
void close()
{
m_pWaveOut->close();
}
혹시.. 풀소스 올려 주실수 있을까요??
답글삭제소스 내용 확인해 보면.. #include "WaveBuffer.h" 파일도 없고..
호출 방법은 open 만 하면 될것 같긴 한데..
예제가 없어 확실하지는 않네요..
추가로.. 파일로 저장하는 방법도 있으면 좋겠구요^^
wavein/waveout 어느쪽을 사용하든 오디오 처리에 대한 기본적인 이해는 있어야하구요. 오디오 덤프파일을 들으려면 GoldWave 로 채널/샘플링레이트 등을 맞춰주면 됩니다.
삭제안녕하세요 ~ 글 잘 읽고 많이 배워갑니다.
답글삭제그런데 한가지 추가하고 싶은게 있는데, 어떤식으로 접근해야 할지 몰라서 혹시나 하는 마음에 질문드립니다. 전 지금 mfc랑 api를 이용해서 녹음기 소스를 만들고 있는데, 저장 방법을 저장 버퍼가 차면 파일로 변환하던지 , 그게 힘들다면 버퍼에 있는 샘플을 가지고 오는 식으로 만들려고 합니다.(녹음기 안에 다른 프로그램을 넣을 예정이거든요.) 혹시 가능하시다면 약간의 도움을 주실수 있을까요?