今天把试了下DirectSound,说实话,用起来还没有PlaySound()方便。但功能却要强得多。
要使用这个组件,首先要用DirectSoundCreate8创建一个LPDIRECTSOUND8对象;
LPDIRECTSOUND8 m_sound; HRESULT hr; hr = DirectSoundCreate8(NULL, &m_sound, NULL); if (FAILED(hr)) { return FALSE; }
然后跟之前所说的DirectInput一样要设置协议。
hr = m_sound->SetCooperativeLevel(m_hwnd, DSSCL_NORMAL); if (FAILED(hr)) { return FALSE; }
有了协议之后就只需要创建一个缓冲区来缓冲我们的wav文件,不过很多书上说什么主缓冲区和次缓冲区。龙儿我也不管那么多了。我就创一个缓冲区。
不过在之前要知道怎么读取wav文件。龙儿提供一个完整的读取wav文件的函数
BYTE* Dsound::LoadWaveFile(LPSTR filename, DWORD* length) { HMMIO file = mmioOpenA(filename, NULL, MMIO_READ); if (file == NULL) { return NULL; } char ch[4]; mmioSeek(file, 8L, SEEK_SET); mmioRead(file, ch, 4L); if (ch[0] != 'W' || ch[1] != 'A' || ch[2] != 'V' || ch[3] != 'E') { mmioClose(file, 0); return NULL; } mmioSeek(file, 20L, SEEK_SET); mmioRead(file, HPSTR(&m_fmt), sizeof(WAVEFORMATEX)); DWORD len; mmioSeek(file, 40L, SEEK_SET); mmioRead(file, (char*)&len, sizeof(DWORD)); (*length) = len; BYTE* data; data = new BYTE[len]; mmioSeek(file, 44L, SEEK_SET); mmioRead(file, (char*)data, LONG(len)); mmioClose(file, 0); return data; }
其中m_fmt是一个WAVEFORMATEX结构体,将会在接下来的创建缓冲区的时候用到。
创建缓冲区说白了就是真充两个结构体。一个DSBUFFERDESC,还有一个WAVEFORMATEX已经在文件中读取到了。简单吧。。。
DSBUFFERDESC desc; ZeroMemory(&desc, sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STATIC; desc.dwBufferBytes = length; desc.lpwfxFormat = &m_fmt; hr = m_sound->CreateSoundBuffer(&desc, &lpbuffer, NULL); if (FAILED(hr)) { return FALSE; }
缓冲区创建后,就只剩锁定你所创建的缓冲区然后把你从wav文件中读取出来的数据写入缓冲区就行了。
LPVOID lpvPtr; DWORD dwByte; lpbuffer->Lock(0, 0, &lpvPtr, &dwByte, NULL, NULL, DSBLOCK_ENTIREBUFFER); memcpy(lpvPtr, m_data, dwByte); lpbuffer->Unlock(lpvPtr, dwByte, NULL, 0);
终于万事俱备,只欠东风了。就差一个play了。
lpbuffer->SetCurrentPosition(0); lpbuffer->Play(0, 0, DSBPLAY_LOOPING);
然后就听一下音乐享受一下自己的成果吧。
龙儿顺便提供一个这几讲的源码吧。