您的位置:首页 > 编程语言

首战用DirectSound改造waveout,贴出成功播放声音的代码

2014-05-07 22:59 453 查看
以下为设置

HRESULT CPlay_AudioPlay::StartDirectSound()

{

//下面初始化DirectSound工作。

HRESULT hr;

if(FAILED(hr = DirectSoundCreate8(NULL,&m_pDsd,NULL)))

{

return PLAY_USUAL_ERROR;

}

//设置设备的协作度

if(FAILED(hr = m_pDsd->SetCooperativeLevel(m_hwnd,DSSCL_PRIORITY)))

{

return PLAY_USUAL_ERROR;

}

WAVEFORMATEX waveformat;

waveformat.wFormatTag = WAVE_FORMAT_PCM;

waveformat.nChannels = 1;

waveformat.nSamplesPerSec = 8000;

waveformat.wBitsPerSample = 16;

waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample /8;

waveformat.nAvgBytesPerSec = waveformat.nBlockAlign * waveformat.nSamplesPerSec;

DSBUFFERDESC dsbd;

ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );

dsbd.dwSize = sizeof(DSBUFFERDESC);

dsbd.dwFlags = DSBCAPS_GLOBALFOCUS ¦ DSBCAPS_CTRLFX ¦ DSBCAPS_CTRLPOSITIONNOTIFY ¦DSBCAPS_GETCURRENTPOSITION2;

dsbd.dwBufferBytes = waveformat.nAvgBytesPerSec * 4; //Set 3 Second Buffer

dsbd.lpwfxFormat = &waveformat;

LPDIRECTSOUNDBUFFER lpbuffer;

//创建辅助缓冲区对象

if(FAILED(hr = m_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL)))

{

return PLAY_USUAL_ERROR;

}

if( FAILED( hr = lpbuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &m_pDSBuffer8)))

{

return PLAY_USUAL_ERROR;

}

lpbuffer->Release();

//设置通知长度

LPDIRECTSOUNDNOTIFY8 g_pDSNotify = NULL;

DSBPOSITIONNOTIFY g_aPosNotify[AUDIO_BUF_NUM];//设置通知标志的数组

for(int i =0; i < AUDIO_BUF_NUM;i++)

{

g_aPosNotify[i].dwOffset = i* waveformat.nAvgBytesPerSec ;

g_aPosNotify[i].hEventNotify = m_event[i];

}

if(FAILED(hr = m_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID *) &g_pDSNotify )))

return PLAY_USUAL_ERROR;

g_pDSNotify->SetNotificationPositions(AUDIO_BUF_NUM,g_aPosNotify);

g_pDSNotify->Release();

return 0;

}

以下为传送数据

ASample = *((AVSample*)pAudioPlay->m_pAudioData);

pAudioPlay->m_pSynchronism->GetClearanceTime(ASample,lClearanceTime);

lTime = GetTickCount() - lTime;

if(lClearanceTime > 0)

{

// tools.WaitTime(lClearanceTime); //音视频同步播放

}

lTempLen = pAudioPlay->m_lReadLen - sizeof(AVSample);

pAudioPlay->m_pDSBuffer8->Lock(0,0,&(lpLockBufExcursion),&lDataLengthRemain,

&lpLockBufStart,&lDataLengthWrite,DSBLOCK_ENTIREBUFFER);

memcpy(lpLockBufExcursion,pAudioPlay->m_pAudioData + sizeof(AVSample),lTempLen);

TRACE("x=%x,Remain = %d, WriteLength = %d/n",lpLockBufExcursion,lDataLengthRemain,lTempLen);

pAudioPlay->m_pDSBuffer8->Unlock(lpLockBufExcursion,lDataLengthRemain,lpLockBufStart,lDataLengthWrite);

// pAudioPlay->m_pDSBuffer8->SetCurrentPosition(0);

pAudioPlay->m_pDSBuffer8->Play(0,0,DSBPLAY_LOOPING);

// WaitForMultipleObjects (AUDIO_BUF_NUM, pAudioPlay->m_event, FALSE, INFINITE);

数据为单声道立体声,采样率8000,16bit,每个音频包相隔10毫秒。

每次读出数据长度160字节,放入缓冲区。缓冲区64000字节。每次返回的lpLockBufExcursion,lDataLengthRemain都相同

传入的数据使用waveout时是可以播放的,应该不是数据的问题。

我保存了一秒的数据塞进去还是不行。

请问我哪里做错了。

问题解决了,我写数据的时候,总是写在开头,本想着调用Play把数据播放完了,就播放下一帧,写在缓冲区开头应该没问题。

现在我自己记录已经写入的数据总长度,在LOCK时把数据放在已经写入数据的最后。直到填满缓冲区,之后再把总长度置零。

贴出相关代码:

LONG TotalLength = 0;

。。。。。

char * buf = (char*)lpLockBufExcursion;

memcpy(buf + TotalLength,pAudioPlay->m_pAudioData + sizeof(AVSample),lTempLen);

TotalLength += lTempLen;

if(TotalLength >= 64000)

{

TotalLength = 0;

}

后记,总算是把声音放出来了,也总算稍微了解一点DirectSound了。

但像

// pAudioPlay->m_pDSBuffer8->SetCurrentPosition(0);

//WaitForMultipleObjects (AUDIO_BUF_NUM, pAudioPlay->m_event, FALSE, INFINITE);

我都把注释起来了,因为还不会用。暂时先这样吧,之后再有什么经验,我还是会在我的博客上共享的。

国内的奉献精神和学习气氛严重有问题,我在网上查了好几天的资料,发了好几个帖子,竟然没人能够给我什么有用的提示和帮助,中国的程序员很牛X吗?中国的编程水平跟外国都快差一个时代了。中国程序员写出什么给人印象深刻的东西了。

为什么中国人都要表现的那么自私,这才算中国的文化吗?

DirectX是别人的,总是去学习别人的东西怎么用,什么时候才能做出自己的东西,核心的东西。

我把我所有的编程经验都贴出来,因为我想让初学者少走弯路,能更快去研究更高端的东西。我想加速中国的软件发展,即使只有一丝的效果,我也要去做。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: