Chinaunix首页 | 论坛 | 博客
  • 博客访问: 42135
  • 博文数量: 11
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 120
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-10 10:40
文章分类
文章存档

2010年(1)

2008年(1)

2007年(9)

我的朋友
最近访客

分类: WINDOWS

2007-07-19 18:27:13

有几个地方,破脑袋死也想不通,于是先在这里留个记号,防止被我这破脑袋忘掉了
// TestDirecSound.cpp: implementation of the TestDirecSound class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TestDirecSound.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//
void CALLBACK TimerProcess(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
    CTestDirectSound *pDDS = (CTestDirectSound *)dwUser;
    pDDS->TimerCallback();   
}

BOOL CALLBACK DSEnumCallBack(GUID *pGuid, LPCSTR strDesc, LPCSTR strDrvName, void *pContext)
{
    CTestDirectSound *pDDS = (CTestDirectSound *)pContext;
    return pDDS->DSEnumerateCallBack(pGuid, strDesc, strDrvName);
}

CTestDirectSound::CTestDirectSound()
{
    m_lpDSB = NULL;
    m_lpDS = NULL;
    m_lpAudioBuf = NULL;
    m_pHEvent[0] = CreateEvent(NULL, FALSE, FALSE, _T("Direct_Sound_Buffer_Notify_0"));
    m_pHEvent[1] = CreateEvent(NULL, FALSE, FALSE, _T("Direct_Sound_Buffer_Notify_1"));   
    m_dwCircles1 = 0;
    m_dwCircles2 = 0;
    m_fStop = FALSE;
}

CTestDirectSound::~CTestDirectSound()
{
    if (m_lpAudioBuf)
        delete []m_lpAudioBuf;
}

void CTestDirectSound::Play(LPCSTR lpszFileName)
{
    m_fStop = FALSE;
    m_WaveFile.Open((char *)lpszFileName, &m_WFE, WAVEFILE_READ);
    memcpy(&m_WFE, m_WaveFile.GetFormat(), sizeof(m_WFE));

    SetFormat();


    //Write the audio data to DirectSoundBuffer
    LPVOID lpvAudio1 = NULL, lpvAudio2 = NULL;
    DWORD dwBytesAudio1 = 0, dwBytesAudio2 = 0;   
   
    //Lock DirectSoundBuffer
    HRESULT hr = m_lpDSB->Lock(0, m_WFE.nAvgBytesPerSec, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);
    if ( FAILED(hr) ) {
        OutputDebugString("lock directsound buffer failed");
        return;
    }

    DWORD nRetBytes;
    m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
   
    //Init lpvAudio1
    if (NULL != lpvAudio1) {           
        memset(lpvAudio1, 0, dwBytesAudio1);           
    }
   
    //Init lpvAudio2
    if (NULL != lpvAudio2) {           
        memset(lpvAudio2, 0, dwBytesAudio2);           
    }
   
    //Copy Audio Buffer to DirectSoundBuffer
    if (NULL == lpvAudio2) {
        memcpy(lpvAudio1, m_lpAudioBuf, nRetBytes);
    }
    else {
        memcpy(lpvAudio1, m_lpAudioBuf, dwBytesAudio1);
        memcpy(lpvAudio2, m_lpAudioBuf + dwBytesAudio1, dwBytesAudio2);
    }
   
    //Unlock DirectSoundBuffer
    m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2);

    //Beging Play
    m_lpDSB->Play(0, 0, DSBPLAY_LOOPING);
   
    //timeSetEvent
    m_timerID = timeSetEvent(300, 100, TimerProcess, (DWORD)this, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
}

void CTestDirectSound::Stop()
{
    if (NULL != m_lpDSB) {
       
        m_lpDSB->Stop();
        timeKillEvent(m_timerID);
       
        //Empty the buffer
        LPVOID lpvAudio1 = NULL;
        DWORD dwBytesAudio1 = 0;
        HRESULT hr = m_lpDSB->Lock(0, 0, &lpvAudio1, &dwBytesAudio1, NULL, NULL, DSBLOCK_ENTIREBUFFER);
        if ( FAILED(hr) ) {
            OutputDebugString(_T("Lock entirebuffer failed! Stop Failed!"));
            return;
        }
        memset(lpvAudio1, 0, dwBytesAudio1);
        m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, NULL, NULL);
       
        //Move the current play position to begin
        m_lpDSB->SetCurrentPosition(0);   

        //Reset Event
        ResetEvent(m_pHEvent[0]);
        ResetEvent(m_pHEvent[1]);
        //Set Circles1 and Circles2 0
        m_dwCircles1 = 0;
        m_dwCircles2 = 0;

    }   

}

void CTestDirectSound::About()
{
    HRESULT hr;

    hr = DirectSoundEnumerate(DSEnumCallBack, (void *)this);

    if (FAILED(hr))
        AfxMessageBox("Enumerate DirectSound Failed");
}

void CTestDirectSound::TimerCallback()
{   
    放在这个地方就是不行,播放的老快
    //DWORD nRetBytes = 0;
    //m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
    //Write the audio data to DirectSoundBuffer
    LPVOID lpvAudio1 = NULL, lpvAudio2 = NULL;
    DWORD dwBytesAudio1 = 0, dwBytesAudio2 = 0;   
   
    HRESULT hr = WaitForMultipleObjects(2, m_pHEvent, FALSE, 0);
    if (m_fStop) {
        Stop();
        return;
    }

    if(WAIT_OBJECT_0 == hr) {
        m_dwCircles1++;
        //Lock DirectSoundBuffer Second Part
        HRESULT hr = m_lpDSB->Lock(m_WFE.nAvgBytesPerSec, m_WFE.nAvgBytesPerSec, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);
        if ( FAILED(hr) ) {
            OutputDebugString(_T("Lock DirectSoundBuffer Failed!"));
            return;
        }       
    }
    else if (WAIT_OBJECT_0 + 1 == hr) {   
        m_dwCircles2++;
        //Lock DirectSoundBuffer First Part
        HRESULT hr = m_lpDSB->Lock(0, m_WFE.nAvgBytesPerSec, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);
        if ( FAILED(hr) ) {
            OutputDebugString(_T("Lock DirectSoundBuffer Failed!"));
            return;
        }       
    }
    else {
        return;
    }

//就是下面这个东东,放在这个地方才能比较正常的播放
    DWORD nRetBytes = 0;
    m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
   
    //If near the end of the audio data
    if (nRetBytes / m_WFE.nBlockAlign < m_WFE.nSamplesPerSec) {
        m_fStop = TRUE;
        memset(m_lpAudioBuf+nRetBytes, 0, m_WFE.nAvgBytesPerSec - nRetBytes);               
    }

    //Init lpvAudio1
    if (NULL != lpvAudio1) {           
        memset(lpvAudio1, 0, dwBytesAudio1);           
    }
   
    //Init lpvAudio2
    if (NULL != lpvAudio2) {           
        memset(lpvAudio2, 0, dwBytesAudio2);           
    }

    //Copy Audio Buffer to DirectSoundBuffer
    if (NULL == lpvAudio2) {
        memcpy(lpvAudio1, m_lpAudioBuf, nRetBytes);
    }
    else {
        memcpy(lpvAudio1, m_lpAudioBuf, dwBytesAudio1);
        memcpy(lpvAudio2, m_lpAudioBuf + dwBytesAudio1, dwBytesAudio2);
    }
   
    //Unlock DirectSoundBuffer
    m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2);
}

void CTestDirectSound::SetFormat()
{
    //Create DirectSound
    if ( FAILED(DirectSoundCreate(NULL, &m_lpDS, NULL)) ) {
        OutputDebugString(_T("Create DirectSound Failed!"));
        return;
    }
   
    //Set Cooperative Level
    HWND hWnd = GetForegroundWindow();
    if (hWnd == NULL)
    {
        hWnd = GetDesktopWindow();
    }
   
    if ( FAILED(m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY)) ) {
        OutputDebugString(_T("SetCooperativeLevel Failed"));
        return;
    }
   
    //Create Primary Buffer
    DSBUFFERDESC dsbd;
    ZeroMemory(&dsbd, sizeof(dsbd));
    dsbd.dwSize = sizeof(DSBUFFERDESC);
    dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
    dsbd.dwBufferBytes = 0;
    dsbd.lpwfxFormat = NULL;
   
    LPDIRECTSOUNDBUFFER lpDSB = NULL;
    if ( FAILED(m_lpDS->CreateSoundBuffer(&dsbd, &lpDSB, NULL)) ) {
        OutputDebugString(_T("Create Primary Sound Buffer Failed!"));
        return;
    }
   
    //Set Primary Buffer Format
    if ( FAILED(lpDSB->SetFormat(&m_WFE)) ) {
        OutputDebugString(_T("Set Primary Format Failed!"));
        return;
    }
   
    //Create Second Sound Buffer
    dsbd.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS;
    dsbd.dwBufferBytes = 2*m_WFE.nAvgBytesPerSec; //2 Seconds Buffer
    dsbd.lpwfxFormat = &m_WFE;
   
    if ( FAILED(m_lpDS->CreateSoundBuffer(&dsbd, &m_lpDSB, NULL)) ) {
        OutputDebugString(_T("Create Second Sound Buffer Failed!"));
        return;
    }

    //Query DirectSoundNotify
    LPDIRECTSOUNDNOTIFY lpDSBNotify;
    if ( FAILED(m_lpDSB->QueryInterface(IID_IDirectSoundNotify, (LPVOID *)&lpDSBNotify)) ) {
        OutputDebugString(_T("QueryInterface DirectSoundNotify Failed!"));
        return;
    }

    //Set Direct Sound Buffer Notify Position
    DSBPOSITIONNOTIFY pPosNotify[2];
    pPosNotify[0].dwOffset = m_WFE.nAvgBytesPerSec/2 - 1;
    pPosNotify[1].dwOffset = 3*m_WFE.nAvgBytesPerSec/2 - 1;       
    pPosNotify[0].hEventNotify = m_pHEvent[0];
    pPosNotify[1].hEventNotify = m_pHEvent[1];   
   
    if ( FAILED(lpDSBNotify->SetNotificationPositions(2, pPosNotify)) ) {
        OutputDebugString(_T("Set NotificationPosition Failed!"));
        return;
    }   

    //New audio buffer
    if (NULL != m_lpAudioBuf) {
        delete []m_lpAudioBuf;
        m_lpAudioBuf = NULL;       
    }
    m_lpAudioBuf = new BYTE[m_WFE.nAvgBytesPerSec];
   
    //Init Audio Buffer
    memset(m_lpAudioBuf, 0, m_WFE.nAvgBytesPerSec);
}

DWORD CTestDirectSound::GetSamplesPlayed()
{
    if (NULL == m_lpDSB) {
        return 0;
    }
   
    //Get curren play position
    DWORD dwCurPlayPos = 0, dwCurPlaySample = 0;
    m_lpDSB->GetCurrentPosition(&dwCurPlayPos, NULL);
    dwCurPlaySample = dwCurPlayPos/m_WFE.nBlockAlign;
   
    //Caculate the samples played
    DWORD dwSamplesPlayed = 0;
    if (m_dwCircles2 < 1) {
        return dwCurPlaySample;
    }
   
    dwSamplesPlayed = (m_dwCircles2-1)*2*m_WFE.nSamplesPerSec + 3*m_WFE.nSamplesPerSec/2;       
    if (dwCurPlaySample > (3*m_WFE.nSamplesPerSec/2)) {
       
        if (m_dwCircles2 < m_dwCircles1) {
           
            dwSamplesPlayed = (m_dwCircles1-1)*2*m_WFE.nSamplesPerSec + 3*m_WFE.nSamplesPerSec/2;
        }
       
        dwSamplesPlayed += dwCurPlaySample - 3*m_WFE.nSamplesPerSec/2 + 1;               
    }
    else {
       
        dwSamplesPlayed += dwCurPlaySample + m_WFE.nSamplesPerSec/2;
    }
   
    CString strSamplesPlayed;
    strSamplesPlayed.Format(_T("Samples Played: %d \n"), dwSamplesPlayed);
    OutputDebugString(strSamplesPlayed);
   
    return dwSamplesPlayed;
}

BOOL CTestDirectSound::DSEnumerateCallBack(GUID *pGuid, LPCSTR strDesc, LPCSTR strDrvName)
{
    CString tmpStr;

    tmpStr = "\nDevice Name = ";
    tmpStr += strDesc;
    tmpStr += "\nDriver Name = ";
    tmpStr += strDrvName;

    AfxMessageBox(tmpStr);

    return TRUE;
}

//就是下面这个东东,放在这个地方才能比较正常的播放
    DWORD nRetBytes = 0;
    m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
放在lock中才可以正常播放,真搞不懂DirectSound是怎么弄得!!
阅读(1140) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~