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

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

2008-04-17 15:31 627 查看
以下为设置

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是别人的,总是去学习别人的东西怎么用,什么时候才能做出自己的东西,核心的东西。

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