加入音乐是增强应用程序功能的所有方法中最简单的一个。音乐可以使用户心情愉快;在合适的场合播放恰当的音乐能够使程序员和他的VC++程序焕发光彩。
Microsoft Windows Multimedia API提供了三种方法来播放WAV文件: PlaySound()函数。它可以通过单行编码来播放Wave格式的声音。此函数有两个限制:必须将声音数据完整地载入物理内存;数据格式必须被所配置的某一音频驱动器支持。根据经验,PlaySound()适用于100K以下的文件。 MCI(The Media Control Interface)。MCI功能强大,不仅可以实现WAV文件的播放,而且还可以播放MIDI及CD音频。 低级Wave音频设备。用这些设备可以运行完全控制Wave数据的件。 前两种方法使用简单,但无法实现两个及两个以上的WAV文件的播放;第三种方法实现起来非常复杂,非专业人员很难完成。DirectSound可以实现八个及八个以上WAV文件的同时播放,能使多媒体程序更加生动,而且简单易用,但它仅适合于Windows 95下的程序,也不支持WAV文件的记录及存储""这是唯一让人遗憾的地方。实现DirectSound需要以下几个步骤: 1. 创建及初始化DirectSound LPDIRECTSOUND m_pDirectObject;if(DirectSoundCreate(NULL,&m_pDirectObject,NULL)==DS_OK)file://设定应用程序的声音设备优先级别方式,一般为DSSCL_NORMALm_pDirectObject->SetCooperativeLevel(this- >m_hWnd,DSSCL_NORMAL);elseAfxMessageBox("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); file://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) file://格式块指针,类型:LPWAVEFORMATEX m_pFormat = NULL; if (m_pData) file://数据块指针,类型:LPBYTE m_pData = NULL; if (m_dwSize) file://数据长度,类型: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; file://寻找格式块,数据块位置及数据长度 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)); } file://未找到,返回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; file://头文件中声明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; file://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. 关闭。释放内存块,声音缓冲区。 DirectSound需要用到mmsystem.h,dsound.h两个头文件。