VC5.0下实现DirectSound 音乐可以使用户心情愉快,在合适的场合播放恰当的音乐能够使 程序员和他的VC++程序焕发出光彩。 API提供了三种方法来播放WAV文件: * PlaySound()函数。它可以通过单行编码来播放Wave格式的声 音。此函数有两个限制:必须将声音数据完整地载入物理内存;数据格 式必须被所配置的某一音频驱动器支持。根据经验,PlaySound()适用 于100K以下的文件。 * MCI(The Media Control Interface)。MCI功能强大,不仅可以 实现WAV文件的播放,而且还可以播放MIDI及CD音频。 * 低级Wave音频设备。用这些设备可以运行完全控制Wave数据的 应用文件。 前两种方法使用简单,但无法实现两个及两个以上的WAV文件的播 放;第三种方法实现起来非常复杂,非专业人员很难完成。DirectSoun d可以实现八个及八个以上WAV文件的同时播放,能使多媒体程序更加 生动,而且简单易用,但它仅适合于Windows 95下的程序,也不支持WAV 文件的记录及存储——这是唯一让人遗憾的地方。 实现DirectSound需要以下几个步骤: 1. 创建及初始化DirectSound: LPDIRECTSOUND m_pDirectObject; if(DirectSoundCreate(NULL,& m_pDirectObject,NULL)==DS_OK) //设定应用程序的声音设备优先级别方式,一般为DSSCL_NORMAL m_pDirectObject->SetCooperativeLevel(this->m_hWnd,DSSCL_NORMAL); else AfxMessageBox("DirectSound Create failed"); 2. 将WAV文件读入内存,找到格式块、数据块位置及数据长度: m_pMemory,m_pFormat,m_pData,m_dwSize在头文件中声明。 BOOL CDirectWave::LoadFile (CString Filename) { CFile File; DWORD dwSize; if (!File.Open (Filename, CFile::modeRead | CFile::shareDenyNone)) return FALSE; dwSize = File.Seek (0, CFile::end); File.Seek (0, CFile::begin); //m_pMemory内存存储块指针,类型:LPVOID m_pMemory = GlobalAlloc (GMEM_FIXED, dwSize); if (File.ReadHuge (m_pMemory, dwSize) != dwSize){ File.Close (); return FALSE; } File.Close (); LPDWORD pdw,pdwEnd; DWORD dwRiff,dwType, dwLength, dwLength; if (m_pFormat) //格式块指针,类型: LPWAVEFORMATEX m_pFormat = NULL; if (m_pData) //数据块指针,类型:LPBYTE m_pData = NULL; if (m_dwSize) //数据长度,类型:DWORD m_dwSize = 0; pdw = (DWORD *) m_pMemory; dwRiff = *pdw++; dwLength = *pdw++; dwType = *pdw++; if (dwRiff != mmioFOURCC (‘R’, ‘I’, ‘F’, ‘F’)) return FALSE; if (dwType != mmioFOURCC (‘W’, ‘A’, ‘V’, ‘E’)) return FALSE; //寻找格式块,数据块位置及数据长度 pdwEnd = (DWORD *)((BYTE *) pdw + dwLength - 4); while (pdw < pdwEnd){ dwType = *pdw++; dwLength = *pdw++; switch (dwType){ case mmioFOURCC(‘f’, ‘m’, ‘t’, ‘ ’): if (!m_pFormat){ if (dwLength < sizeof (WAVEFORMAT)) return FALSE; m_pFormat = (LPWAVEFORMATEX) pdw; if (m_pData && m_dwSize) return TRUE; } break; case mmioFOURCC(‘d’, ‘a’, ‘t’, ‘a’): if (!m_pData || !m_dwSize){ m_pData = (LPBYTE) pdw; m_dwSize = dwLength; if (m_pFormat) return TRUE; } break; } pdw = (DWORD *)((BYTE *) pdw + ((dwLength + 1) &~ 1)); } //未找到,返回FALSE return FALSE; } 3. 创建声音缓冲区: DSBUFFERDESC BufferDesc; memset (&BufferDesc, 0, sizeof (BufferDesc)); BufferDesc.lpwfxFormat = (LPWAVEFORMATEX) m_pFormat; BufferDesc.dwSize = sizeof (DSBUFFERDESC); BufferDesc.dwBufferBytes = m_dwSize; BufferDesc.dwFlags = 0; //头文件中声明m_pDSoundBuffer,类型: LPDIRECTSOUNDBUFFER if (pDSoundObject->CreateSoundBuffer (& BufferDesc, &m_pDSoundBuffer, 0) != DS_OK) return FALSE; 4. 载入声音数据: BOOL CDirectWave::LoadData (void){ LPVOID lpPtr1, lpPtr2; DWORD dwLen1, dwLen2; HRESULT hResult; TryLoad: hResult = m_pDSoundBuffer->Lock (0, m_dwSize, &lpPtr1, &dwLen1, &lpPtr2, &dwLen2, 0); if (hResult == DS_OK){ memcpy (lpPtr1, m_pData, dwLen1); if (lpPtr2)  memcpy (lpPtr2, m_pData + dwLen1, dwLen2); m_pDSoundBuffer->Unlock (lpPtr1, dwLen1, lpPtr2, dwLen2);  return TRUE; } else if (hResult == DSERR_BUFFERLOST){ hResult = m_pDSoundBuffer->Restore (); if (hResult == DS_OK) goto TryLoad; } return FALSE; } 5. 播放及停止: void CDirectWave::Play (BOOL bLoop){ DWORD dwFlags = 0;//dwFlags= DSBPLAY_LOOPING可实现循环播放 TryPlay: if (m_pDSoundBuffer->Play (0, 0, dwFlags) == DSERR_BUFFERLOST){  if (LoadData ())//数据丢失,重新装载 goto TryPlay; } } void CDirectWave::Stop (void){ m_pDSoundBuffer->Stop (); } 6. 关闭、释放内存块、声音缓冲区。