void GameAudio::registerMusic(MusicTypes muType, LPWSTR wavFilePath) { CWaveFile wav; /// wav file will be destroyed at the end of this function //// All the file references are rooted at the directory "Apps/Rebelle/data" bool wavOpenSuccess = SUCCEEDED(wav.Open(wavFilePath, 0, WAVEFILE_READ)); WAVEFORMATEX *format = wav.GetFormat(); unsigned long wavSize = wav.GetSize(); unsigned char *wavData = new unsigned char[wavSize]; bool wavReadSuccess = SUCCEEDED(wav.Read(wavData, wavSize, &wavSize)); IXAudio2SourceVoice* srcVoice; /// this will be stored in the map of this class bool csvSuccess = SUCCEEDED(xAudio2Engine->CreateSourceVoice(&srcVoice, format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, 0, 0, 0)); XAUDIO2_BUFFER *bufferPrototype = new XAUDIO2_BUFFER(); bufferPrototype->pAudioData = wavData; bufferPrototype->Flags = XAUDIO2_END_OF_STREAM; bufferPrototype->AudioBytes = wavSize; //// register sound buffer prototype musicBufferPrototypeMap[muType] = bufferPrototype; //// mark this sourceVoice as registered musicRegistrationMap[muType] = true; //// store the source voice musicMap[muType] = srcVoice; }
HRESULT FrkSound::LoadAudio(const tchar* audioPath) { HRESULT result; CWaveFile audioObject; result = audioObject.Open(LPTSTR(audioPath), 0, WAVEFILE_READ); if (!FAILED(result)) { m_hBufferDescription.dwBufferBytes = audioObject.GetSize(); m_hBufferDescription.lpwfxFormat = audioObject.m_pwfx; result = m_hAudioHandler->CreateSoundBuffer(&m_hBufferDescription, &m_hSoundBuffer, 0); VOID* pointerToLockBuffer = 0; DWORD lockSize = 0; result = result | (m_hSoundBuffer)->Lock(0, AUDIO_BUFFER_SIZE, &pointerToLockBuffer, &lockSize, 0, 0, DSBLOCK_ENTIREBUFFER); if (!FAILED(result)) { DWORD readedData = 0; audioObject.ResetFile(); result = audioObject.Read((BYTE*)pointerToLockBuffer, lockSize, &readedData); if (!FAILED(result)) { (m_hSoundBuffer)->Unlock(pointerToLockBuffer, lockSize, 0, 0); } } } audioObject.Close(); return result; }
// ----------------------------------------------- // Load am thanh vao buffer // ----------------------------------------------- HRESULT Sound::loadAudio(const char* audioPath_) { HRESULT result; CWaveFile audioObject; result = audioObject.Open(LPTSTR(audioPath_), 0, 1); if (!FAILED(result)) { _bufferDescription.dwBufferBytes = audioObject.GetSize(); _bufferDescription.lpwfxFormat = audioObject.m_pwfx; result = _audioHandler->CreateSoundBuffer(&_bufferDescription, &_soundBuffer, 0); VOID* pointerToLockedBuffer = 0; DWORD lockedSize = 0; result = result | (_soundBuffer)->Lock(0, AUDIO_BUFFER_SIZE, &pointerToLockedBuffer, &lockedSize, 0, 0, DSBLOCK_ENTIREBUFFER); if (!FAILED(result)) { DWORD readedData = 0; audioObject.ResetFile(); result = audioObject.Read((BYTE*)pointerToLockedBuffer, lockedSize, &readedData); if (!FAILED(result)) { (_soundBuffer)->Unlock(pointerToLockedBuffer, lockedSize, 0, 0); } } } audioObject.Close(); return result; }
CXAudio2::IntCacheIterator CXAudio2::_PreCacheResource(int ID) { // File already in cache IntCacheIterator i = resourceCache.find(ID); if (i != resourceCache.end()) return i; // Load WAV (PCM, ADPCM, xWMA). OGG not supported via resources. // Wave file reading class; from the SDK samples CWaveFile wav; hr = wav.Open(MAKEINTRESOURCE(ID), 0, WAVEFILE_READ, true); if (FAILED(hr)) throw CXAudio2Error(hr, "Failed to load file from disk. Check the filename exists and that the file is of a supported format."); DWORD size = wav.GetSize(); BYTE* pBuffer = new BYTE[size]; // Read WAV data hr = wav.Read(pBuffer, size, &size); if (FAILED(hr)) { delete[] pBuffer; throw CXAudio2Error(hr, "Failed to read WAV data. Check the WAV file encoding is supported."); } // Make a cache entry of the WAV data now // Avoid invocation of CacheEntry copy constructor which copies pBuffer's memory //fileCache[filename] = CacheEntry(pwfx, pBuffer, size); resourceCache[ID] = CacheEntry(this); i = resourceCache.find(ID); CacheEntry& ce = i->second; // xWMA if (wav.m_bIsXWMA) { ce.SetWma((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size, wav.m_nPacketCount, wav.m_aDecodedPacketCumulativeBytes); } // PCM or ADPCM else { // Cache entry now has reference count 1 and responsibility for deleting pBuffer ce.Set((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size); } ce.refCount = 0; // Just precached, nothing referencing yet totalCacheSize += size; return i; }
/* ================= - Play sound. ================= */ void cXAudio::playSound(LPWSTR theFilename, bool pLoop ) // Play sound { HRESULT hResult; CWaveFile wavFile; wavFile.Open( theFilename, NULL, WAVEFILE_READ ); // Get format of wave file WAVEFORMATEX* pwfx = wavFile.GetFormat(); // Calculate how many bytes and samples are in the wave DWORD cbWaveSize = wavFile.GetSize(); // Read the sample data into memory BYTE* pbWaveData = new BYTE[ cbWaveSize ]; wavFile.Read( pbWaveData, cbWaveSize, &cbWaveSize ); // Submit the wave sample data using an XAUDIO2_BUFFER structure XAUDIO2_BUFFER buffer = {0}; buffer.pAudioData = pbWaveData; buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer buffer.AudioBytes = cbWaveSize; if (pLoop) { buffer.LoopLength = 0; buffer.LoopCount = XAUDIO2_LOOP_INFINITE; } // Create the source voice if( FAILED( hResult = mXAudio2->CreateSourceVoice( &mSourceVoice, pwfx ) ) ) { OutputDebugString("Error creating source voice\n"); delete pbWaveData; } else { mSourceVoice->SubmitSourceBuffer(&buffer); mSourceVoice->Start(0, XAUDIO2_COMMIT_NOW ); } }
/* Loads a sound with the specified id and path */ void XAudioSoundSystem::OnLoadSound(uint32 soundID, const char* szSoundPath) { if(mSounds[soundID] != NULL) return; HRESULT hr = S_OK; char szFullPath[1024]; sprintf_s(szFullPath, 1024, "Data/Win32/%s", szSoundPath); size_t convertedChars = 0; wchar_t wpath[1024]; mbstowcs_s(&convertedChars, wpath, strlen(szFullPath) + 1, szFullPath, _TRUNCATE); // // Read in the wave file // CWaveFile wav; if( FAILED( hr = wav.Open( wpath, NULL, WAVEFILE_READ ) ) ) { wprintf( L"Failed reading WAV file: %#X (%s)\n", hr, wpath ); return; } // Get format of wave file WAVEFORMATEX* pwfx = wav.GetFormat(); // Calculate how many bytes and samples are in the wave DWORD cbWaveSize = wav.GetSize(); // Read the sample data into memory BYTE* pbWaveData = new BYTE[ cbWaveSize ]; if( FAILED( hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) ) { wprintf( L"Failed to read WAV data: %#X\n", hr ); SAFE_DELETE_ARRAY( pbWaveData ); return; } // // Play the wave using a XAudio2SourceVoice // // Create the source voice IXAudio2SourceVoice* pSourceVoice; if( FAILED( hr = mXAudio2->CreateSourceVoice( &pSourceVoice, pwfx ) ) ) { wprintf( L"Error %#X creating source voice\n", hr ); SAFE_DELETE_ARRAY( pbWaveData ); return; } // Submit the wave sample data using an XAUDIO2_BUFFER structure XAUDIO2_BUFFER buffer = {0}; buffer.pAudioData = pbWaveData; buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer buffer.AudioBytes = cbWaveSize; if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) ) { wprintf( L"Error %#X submitting source buffer\n", hr ); pSourceVoice->DestroyVoice(); SAFE_DELETE_ARRAY( pbWaveData ); return; } Sound* pSound = new Sound(); pSound->mVoice = pSourceVoice; pSound->mAudioBuffer = buffer; pSound->mData = pbWaveData; pSound->mStarted = false; mSounds[soundID] = pSound; }
//-------------------------------------------------------------------------------------- bool CAudioData::LoadWaveFile( TCHAR* szWave ) { Cleanup(); // Cleanup just in case we already have data CWaveFile waveFile; // Create a wave file object // Open the wave file if( FAILED( waveFile.Open( szWave, NULL, WAVEFILE_READ ) ) ) { waveFile.Close(); return false; } // Get some information about the sound data WAVEFORMATEX* pwfx = waveFile.m_pwfx; WAVEFORMATEXTENSIBLE* pwfex = NULL; WORD wBitsPerSample = pwfx->wBitsPerSample; if( 0 == wBitsPerSample ) { // We don't support compressed formats return false; } // hold onto this data CopyMemory( &m_wfx, pwfx, sizeof( WAVEFORMATEX ) ); // Get the number of channels if( WAVE_FORMAT_PCM == pwfx->wFormatTag ) { m_ulNumChannels = pwfx->nChannels; } else if( WAVE_FORMAT_EXTENSIBLE == pwfx->wFormatTag ) { pwfex = ( WAVEFORMATEXTENSIBLE* )pwfx; if( KSDATAFORMAT_SUBTYPE_PCM == pwfex->SubFormat || KSDATAFORMAT_SUBTYPE_IEEE_FLOAT == pwfex->SubFormat ) { m_ulNumChannels = NumSetBitsInDWORD( pwfex->dwChannelMask ); } else { // We don't support compressed formats return false; } } // Get the size of the PCM sound data DWORD dwDataSize = waveFile.GetSize(); // Calculate the number of samples m_ulNumSamples = dwDataSize / ( m_ulNumChannels * ( wBitsPerSample / 8 ) ); // Allocate a buffer for each channel m_ppChannel = new float*[ m_ulNumChannels ]; if( !m_ppChannel ) { waveFile.Close(); return false; } ZeroMemory( m_ppChannel, sizeof( float* ) * m_ulNumChannels ); for( unsigned long i = 0; i < m_ulNumChannels; i++ ) { m_ppChannel[i] = new float[ m_ulNumSamples ]; if( !m_ppChannel[i] ) { waveFile.Close(); Cleanup(); return false; } } // Allocate a buffer big enough to hold the wave data m_ulBitsSize = dwDataSize; m_pBits = new unsigned char[ dwDataSize ]; if( !m_pBits ) { waveFile.Close(); Cleanup(); return false; } // Read in the wave data DWORD dwBytesRead = 0; if( FAILED( waveFile.Read( m_pBits, dwDataSize, &dwBytesRead ) ) ) { waveFile.Close(); SAFE_DELETE_ARRAY( m_pBits ); Cleanup(); return false; } // Split the big data into samples switch( wBitsPerSample ) { case 8: SplitDataIntoChannels_8Bit( m_pBits ); break; case 16: SplitDataIntoChannels_16Bit( m_pBits ); break; case 32: if( pwfex ) { if( KSDATAFORMAT_SUBTYPE_PCM == pwfex->SubFormat ) SplitDataIntoChannels_32Bit( m_pBits ); else if( KSDATAFORMAT_SUBTYPE_IEEE_FLOAT == pwfex->SubFormat ) SplitDataIntoChannels_IEEEFloat( m_pBits ); } break; }; // Close the wave file waveFile.Close(); return true; }
bool DXSoundBuffer::LoadWaveToSoundBuffer(std::string wavFilename) { CWaveFile *wavFile; HRESULT hr; wavFile = new CWaveFile(); wavFile->Open((char*)wavFilename.c_str(), NULL, WAVEFILE_READ); if (wavFile->GetSize() == 0) { OutputDebugString("[SoundBuffer.cpp] Cannot init. DXSoundBuffer::LoadWaveToSoundBuffer(std::string wavFilename)"); return false; } DSBUFFERDESC dsbd; ZeroMemory(&dsbd, sizeof(DSBUFFERDESC)); dsbd.dwSize = sizeof(DSBUFFERDESC); //dsbd.dwFlags = 0; dsbd.dwFlags = DSBCAPS_CTRLVOLUME; dsbd.dwBufferBytes = wavFile->GetSize(); dsbd.guid3DAlgorithm = GUID_NULL; dsbd.lpwfxFormat = wavFile->m_pwfx; hr = _pDS->CreateSoundBuffer(&dsbd, &_soundBuffer, NULL); if FAILED(hr) { OutputDebugString("[SoundBuffer.cpp] Cannot init. DXSoundBuffer::LoadWaveToSoundBuffer(std::string wavFilename)"); return false; } VOID* pDSLockedBuffer = NULL; // Pointer to locked buffer memory DWORD dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer DWORD dwWavDataRead = 0; // Amount of data read from the wav file hr = _soundBuffer->Lock(0, wavFile->GetSize(), &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L); if FAILED(hr) return false; // Reset the wave file to the beginning wavFile->ResetFile(); // Read the wave file hr = wavFile->Read((BYTE*)pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead); // Check to make sure that this was successful if FAILED(hr) return false; // Check to make sure the wav file is not empty if (dwWavDataRead == 0) { // Wav is blank, so just fill with silence FillMemory((BYTE*)pDSLockedBuffer, dwDSLockedBufferSize, (BYTE)(wavFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0)); } else if (dwWavDataRead < dwDSLockedBufferSize) { // Don't repeat the wav file, just fill in silence FillMemory((BYTE*)pDSLockedBuffer + dwWavDataRead, dwDSLockedBufferSize - dwWavDataRead, (BYTE)(wavFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0)); } // Unlock the buffer, we don't need it anymore. _soundBuffer->Unlock(pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0); // Clean up delete wavFile; return true; }
CXAudio2::StringCacheIterator CXAudio2::_PreCacheFile(std::string filename) { // File already in cache StringCacheIterator i = fileCache.find(filename); if (i != fileCache.end()) return i; // Check for OGG file std::string ext = filename; ext.erase(0, ext.length() - 4); // Load OGG file if (_stricmp(ext.c_str(), ".ogg") == 0 || _stricmp(ext.c_str(), ".oga") == 0) { #ifdef XAUDIO2_OGGVORBIS FILE* f = fopen(filename.c_str(), "rb"); if (f == NULL) throw CXAudio2Error(E_FAIL, std::string("Error loading file '") + filename + "'. Check the file exists and is valid."); OggVorbis_File oggFile; ov_open(f, &oggFile, NULL, 0); // Takes control of f; no need to call fclose() vorbis_info* pInfo = ov_info(&oggFile, -1); int endian = 0; // 0 for Little-Endian, 1 for Big-Endian int bytesRead = 0; int bitStream; // Read the file data vector<char> oggData; char readbuffer[XAUDIO2_OGGVORBIS_BUFFERSIZE]; do { // Read up to a buffer's worth of decoded sound data bytesRead = ov_read(&oggFile, readbuffer, XAUDIO2_OGGVORBIS_BUFFERSIZE, endian, 2, 1, &bitStream); // Append to end of buffer oggData.insert(oggData.end(), readbuffer, readbuffer + bytesRead); } while (bytesRead > 0); // Fill out a WAVEFORMATEX for the decompressed OGG WAVEFORMATEX wfx; memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.cbSize = sizeof(WAVEFORMATEX); wfx.nChannels = pInfo->channels; wfx.nSamplesPerSec = pInfo->rate; wfx.wBitsPerSample = 16; // OGG is always 16 bit wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nChannels * 2; wfx.nBlockAlign = 2 * wfx.nChannels; wfx.wFormatTag = WAVE_FORMAT_PCM; ov_clear(&oggFile); // Copy the vector which is local scope and will deallocate: the cache takes responsibility for deleting BYTE* pBuffer = new BYTE[oggData.size()]; memcpy(pBuffer, &(oggData.front()), oggData.size()); // Make a cache entry of the WAV data now // Avoid invocation of CacheEntry copy constructor which copies pBuffer's memory //fileCache[filename] = CacheEntry(pwfx, pBuffer, size); fileCache[filename] = CacheEntry(this); i = fileCache.find(filename); CacheEntry& ce = i->second; ce.Set((GENERICWAVEFILE*)&wfx, pBuffer, oggData.size()); ce.refCount = 0; // Just precached, nothing referencing yet ce.isOgg = true; totalCacheSize += oggData.size(); return i; #else // Not built with OGG Vorbis support; throw an error throw CXAudio2Error(E_FAIL, "OGG Vorbis is not supported by this version of XAudio2."); #endif } else { // Load WAV (PCM, ADPCM, xWMA) // Wave file reading class; from the SDK samples CWaveFile wav; // Dumb function definition needs an LPSTR, not an LPCSTR TCHAR* fileNameStr = new TCHAR[filename.size() + 1]; memcpy(fileNameStr, filename.c_str(), filename.size() + 1); // copy null terminator in hr = wav.Open(fileNameStr, 0, WAVEFILE_READ); delete[] fileNameStr; if (FAILED(hr)) throw CXAudio2Error(hr, "Failed to load file from disk. Check the filename exists and that the file is of a supported format."); DWORD size = wav.GetSize(); BYTE* pBuffer = new BYTE[size]; // Read WAV data hr = wav.Read(pBuffer, size, &size); if (FAILED(hr)) { delete[] pBuffer; throw CXAudio2Error(hr, "Failed to read WAV data. Check the WAV file encoding is supported."); } // Make a cache entry of the WAV data now // Avoid invocation of CacheEntry copy constructor which copies pBuffer's memory //fileCache[filename] = CacheEntry(pwfx, pBuffer, size); fileCache[filename] = CacheEntry(this); i = fileCache.find(filename); CacheEntry& ce = i->second; // xWMA if (wav.m_bIsXWMA) { ce.SetWma((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size, wav.m_nPacketCount, wav.m_aDecodedPacketCumulativeBytes); } // PCM or ADPCM else { // Cache entry now has reference count 1 and responsibility for deleting pBuffer ce.Set((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size); } ce.refCount = 0; // Just precached, nothing referencing yet totalCacheSize += size; return i; } }