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; }
bool CN3SndObj::Create(const std::string& szFN, e_SndType eType) { if(NULL == s_lpDS) return false; if(SNDTYPE_2D != eType && SNDTYPE_3D != eType) return false; if(m_lpDSBuff) this->Init(); CWaveFile WaveFile; HRESULT hr = WaveFile.Open(szFN.c_str(), NULL, 1); //#define WAVEFILE_READ 1 if(FAILED(hr)) { #ifdef _N3GAME if(!szFN.empty()) CLogWriter::Write("CN3SndEng::LoadSource - WaveFile Open Failed.. (%s)", szFN.c_str()); #endif return false; } DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwBufferBytes = WaveFile.GetSize(); dsbd.lpwfxFormat = WaveFile.m_pwfx; if(SNDTYPE_2D == eType) // 2D 음원 { dsbd.dwFlags = DSBCAPS_CTRLVOLUME; // | DSBCAPS_STATIC; } else if(SNDTYPE_3D == eType) //3D 음원.. { dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE; // | DSBCAPS_STATIC; dsbd.guid3DAlgorithm = DS3DALG_HRTF_LIGHT; } hr = s_lpDS->CreateSoundBuffer( &dsbd, &m_lpDSBuff, NULL ); if(FAILED(hr)) { #ifdef _N3GAME CLogWriter::Write("CN3SndObj::Create - CreateSoundBuffer Failed.. (%)", szFN.c_str()); #endif return false; } if(!FillBufferWithSound(&WaveFile)) { #ifdef _N3GAME CLogWriter::Write("CN3SndObj::Create - FillBufferWithSound Failed.. (%)", szFN.c_str()); #endif return false; } m_lpDSBuff->SetCurrentPosition(0); if(SNDTYPE_3D == eType) //3D 음원.. if(S_OK != m_lpDSBuff->QueryInterface(IID_IDirectSound3DBuffer, (VOID**)(&m_lpDS3DBuff))) return false; m_szFileName = szFN; // 파일 이름을 기록한다.. s_bNeedDeferredTick = true; // 3D Listener CommitDeferredSetting return true; }
int CSound::playSpeech(CDialogueFile *dialogueFile, int speechId, CProximity &prox) { CWaveFile *waveFile = loadSpeech(dialogueFile, speechId); if (!waveFile) return -1; prox._soundDuration = waveFile->getDuration(); activateSound(waveFile, prox._disposeAfterUse); return _soundManager.playSound(*waveFile, prox); }
BOOL DirectSoundManager::CreateSound(TCHAR *FileName,DirectSoundBuffer &Buffer) { DSBUFFERDESC BufferDesc; WAVEFORMATEX WaveFormat; CWaveFile InputWave; if(DirectSound == NULL) return FALSE; // Load the specified wave file: if ( !InputWave.Load ( FileName ) ) return FALSE; // Make the format of the sound buffer to be created match the // format of the wave file just loaded: InputWave.GetWaveFormat ( WaveFormat ); // Specify the options of the sound buffer to be created: BufferDesc.dwSize = sizeof ( DSBUFFERDESC ); // Require that the buffer have pan, volume, frequency, and // position notification capability (if just basic playback is // desired, specifiy DSBCAPS_STATIC and nothing else): BufferDesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_STATIC | DSBCAPS_CTRLPOSITIONNOTIFY; BufferDesc.dwBufferBytes = InputWave.GetDataSize (); BufferDesc.dwReserved = 0; BufferDesc.lpwfxFormat = &WaveFormat; // Create the sound buffer: if ( DirectSound->CreateSoundBuffer ( &BufferDesc, &Buffer.Buffer, NULL ) != DS_OK ) return FALSE; // Close the input wave file so the sound buffer can access the // file to load the wave data: InputWave.Close (); // Have the sound buffer load its wave data: Buffer.Load ( FileName ); return TRUE; }
CWaveFile *QSoundManager::loadSpeech(CDialogueFile *dialogueFile, int speechId) { CWaveFile *waveFile = new CWaveFile(); // Try to load the specified sound if (!waveFile->loadSpeech(dialogueFile, speechId)) { delete waveFile; return nullptr; } return waveFile; }
CWaveFile *QSoundManager::loadMusic(const CString &name) { CWaveFile *waveFile = new CWaveFile(); // Try to load the specified sound if (!waveFile->loadMusic(name)) { delete waveFile; return nullptr; } return waveFile; }
int CSound::playSound(const CString &name, CProximity &prox) { CWaveFile *waveFile = loadSound(name); if (!waveFile) return -1; prox._soundDuration = waveFile->getDuration(); if (prox._soundType != Audio::Mixer::kPlainSoundType) waveFile->_soundType = prox._soundType; activateSound(waveFile, prox._disposeAfterUse); return _soundManager.playSound(*waveFile, prox); }
uint CTrueTalkManager::readDialogueSpeech() { _speechDuration = 0; for (uint idx = 0; idx < _titleEngine._indexes.size(); ++idx) { CWaveFile *waveFile = _gameManager->_sound.getTrueTalkSound( _dialogueFile, _titleEngine._indexes[idx] - _dialogueId); if (waveFile) { _speechDuration += waveFile->getDurationTicks(); } } return _speechDuration; }
//----------------------------------------------------------------------------- // Name: ValidateWaveFile() // Desc: Open the wave file with the helper // class CWaveFile to make sure it is valid //----------------------------------------------------------------------------- VOID ValidateWaveFile( HWND hDlg, TCHAR* strFileName ) { HRESULT hr; CWaveFile waveFile; // Verify the file is small HANDLE hFile = CreateFile( strFileName, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if( hFile != NULL ) { // If you try to open a 100MB wav file, you could run out of system memory with this // sample cause it puts all of it into a large buffer. If you need to do this, then // see the "StreamData" sample to stream the data from the file into a sound buffer. DWORD dwFileSizeHigh = 0; DWORD dwFileSize = GetFileSize( hFile, &dwFileSizeHigh ); CloseHandle( hFile ); if( dwFileSizeHigh != 0 || dwFileSize > 1000000 ) { waveFile.Close(); SetDlgItemText( hDlg, IDC_STATUS, TEXT("File too large. You should stream large files.") ); return; } } // Load the wave file if( FAILED( hr = waveFile.Open( strFileName, NULL, WAVEFILE_READ ) ) ) { DXTRACE_ERR_MSGBOX( TEXT("Open"), hr ); waveFile.Close(); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Bad wave file.") ); } else // The load call succeeded { // Update the UI controls to show the sound as the file is loaded waveFile.Close(); EnablePlayUI( hDlg, TRUE ); SetDlgItemText( hDlg, IDC_FILENAME, strFileName ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded.") ); strcpy( m_strWaveFileName, strFileName ); // Get the samples per sec from the wave file DWORD dwSamplesPerSec = waveFile.m_pwfx->nSamplesPerSec; // Set the slider positions SetSlidersPos( hDlg, dwSamplesPerSec, 0, 0 ); } }
//计算WAV文件播放时间,这个时间由数据大小和格式共同决定 DWORD GetSoundLength(LPSTR strFileName){ CWaveFile* pWav; DWORD dwLen = 0; DWORD dwSize; WAVEFORMATEX* pwfx; pWav = new CWaveFile(); if (SUCCEEDED(pWav->Open(strFileName, NULL, WAVEFILE_READ)))){ pwfx = pWav->GetFormat(); dwSize = pWav->GetSize(); dwLen = (DWORD)(1000 * dwSize / pwfx->nAvgBytesPerSec); pWav->Close(); } if (pWav) delete pWav; return dwLen; }
HRESULT SaveWavToFile( MyDirectSoundBuffer* o, const void* data, DWORD size, const char* filepath ) { // The WAVEFORMATEX structure can have a variable length that depends on the details of the format. // Before retrieving the format description, the application should query the DirectSoundBuffer object // for the size of the format by calling this method and specifying NULL for the lpwfxFormat parameter. // The size of the structure will be returned in the lpdwSizeWritten parameter. DWORD bytesToAllocate = 0; V_RET(o->m_pDSoundBuffer->GetFormat(NULL, 0, &bytesToAllocate)); WAVEFORMATEX* lpwfxFormat = (WAVEFORMATEX*) alloca( bytesToAllocate ); V_RET(o->m_pDSoundBuffer->GetFormat(lpwfxFormat, bytesToAllocate, NULL)); #ifdef FOLDER_TO_SAVE_WAVEFORMATEX { const UINT64 format_hash = MurmurHash64( lpwfxFormat, bytesToAllocate ); // generate unique file name char buffer[32]; sprintf(buffer, "%016llX", format_hash); char filepath[MAX_PATH]; strcpy_s(filepath, FOLDER_TO_SAVE_WAVEFORMATEX); strcat_s(filepath, buffer); strcat_s(filepath, ".wav_header"); FILE* pFile = ::fopen( filepath, "w" ); if( pFile ) { ::fwrite( lpwfxFormat, sizeof(char), bytesToAllocate, pFile ); ::fclose( pFile ); pFile = NULL; } } #endif CWaveFile waveFile; V_RET(waveFile.Open( (char*)filepath, lpwfxFormat, WAVEFILE_WRITE )); UINT bytesWritten; V_RET(waveFile.Write( size, (BYTE*)data, &bytesWritten )); V_RET(waveFile.Close()); return S_OK; }
//----------------------------------------------------------------------------- // Name: ValidateWaveFile() // Desc: Open the wave file with the helper // class CWaveFile to make sure it is valid //----------------------------------------------------------------------------- HRESULT ValidateWaveFile( HWND hDlg, TCHAR* strFileName ) { HRESULT hr; CWaveFile waveFile; if( -1 == GetFileAttributes(strFileName) ) return E_FAIL; // Load the wave file if( FAILED( hr = waveFile.Open( strFileName, NULL, WAVEFILE_READ ) ) ) { waveFile.Close(); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Bad wave file.") ); return DXTRACE_ERR( TEXT("Open"), hr ); } else // The load call succeeded { WAVEFORMATEX* pwfx = waveFile.GetFormat(); if( pwfx->wFormatTag != WAVE_FORMAT_PCM ) { // Sound must be PCM when using DSBCAPS_CTRLFX SAFE_RELEASE( g_pIGargle ); SAFE_DELETE( g_pSound ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be PCM for effects control.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return S_FALSE; } // Update the UI controls to show the sound as the file is loaded waveFile.Close(); EnablePlayUI( hDlg, TRUE ); SetDlgItemText( hDlg, IDC_FILENAME, strFileName ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded.") ); strcpy( g_strWaveFileName, strFileName ); // Get the samples per sec from the wave file DWORD dwSamplesPerSec = waveFile.m_pwfx->nSamplesPerSec; return S_OK; } }
BOOL DirectSoundBuffer::Load(TCHAR *File) { CWaveFile InputWave; LPVOID BufferPointer; DWORD Bytes1; if ( Buffer == NULL ) return false; // Save the file name of the wave for restoration of the sound // buffer when it is lost: if ( File != FileName ) lstrcpy ( FileName, File ); // Load the specified wave file: if ( !InputWave.Load ( FileName ) ) return false; // Store the wave format in case it's needed later: InputWave.GetWaveFormat ( WaveFormat ); // Lock the sound buffer to obtain a pointer to the memory where // its wave data is stored: if ( Buffer->Lock ( 0, 0, &BufferPointer, &Bytes1, NULL, NULL, DSBLOCK_ENTIREBUFFER ) != DS_OK ) return false; DataSize = InputWave.GetDataSize (); // Store the wave data in the sound buffer: if ( !InputWave.GetData ( BufferPointer, DataSize ) ) return false; // Unlock the sound buffer: if ( Buffer->Unlock ( BufferPointer, DataSize, NULL, NULL ) != DS_OK ) return false; return true; }
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; }
/* ================= - 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 ); } }
// ----------------------------------------------- // 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; }
//----------------------------------------------------------------------------- // Name: CSoundManager::Create() // Desc: //----------------------------------------------------------------------------- HRESULT CSoundManager::Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNumBuffers ) { HRESULT hr; HRESULT hrRet = S_OK; DWORD i; LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; DWORD dwDSBufferSize = NULL; CWaveFile* pWaveFile = NULL; if( m_pDS == NULL ) return CO_E_NOTINITIALIZED; if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) return E_INVALIDARG; apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; if( apDSBuffer == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile = new CWaveFile(); if( pWaveFile == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); if( pWaveFile->GetSize() == 0 ) { // Wave is blank, so don't create it. hr = E_FAIL; goto LFail; } // Make the DirectSound buffer the same size as the wav file dwDSBufferSize = pWaveFile->GetSize(); // Create the direct sound buffer, and only request the flags needed // since each requires some overhead and limits if the buffer can // be hardware accelerated DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwCreationFlags; dsbd.dwBufferBytes = dwDSBufferSize; dsbd.guid3DAlgorithm = guid3DAlgorithm; dsbd.lpwfxFormat = pWaveFile->m_pwfx; // DirectSound is only guarenteed to play PCM data. Other // formats may or may not work depending the sound card driver. hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); // Be sure to return this error code if it occurs so the // callers knows this happened. if( hr == DS_NO_VIRTUALIZATION ) hrRet = DS_NO_VIRTUALIZATION; if( FAILED(hr) ) { // DSERR_BUFFERTOOSMALL will be returned if the buffer is // less than DSBSIZE_FX_MIN and the buffer is created // with DSBCAPS_CTRLFX. // It might also fail if hardware buffer mixing was requested // on a device that doesn't support it. DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } // Default to use DuplicateSoundBuffer() when created extra buffers since always // create a buffer that uses the same memory however DuplicateSoundBuffer() will fail if // DSBCAPS_CTRLFX is used, so use CreateSoundBuffer() instead in this case. if( (dwCreationFlags & DSBCAPS_CTRLFX) == 0 ) { for( i=1; i<dwNumBuffers; i++ ) { if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) { DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); goto LFail; } } } else { for( i=1; i<dwNumBuffers; i++ ) { hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL ); if( FAILED(hr) ) { DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } } } // Create the sound *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags ); SAFE_DELETE_ARRAY( apDSBuffer ); return hrRet; LFail: // Cleanup SAFE_DELETE( pWaveFile ); SAFE_DELETE_ARRAY( apDSBuffer ); return hr; }
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; }
//----------------------------------------------------------------------------- // Name: OnOpenSoundFile() // Desc: Called when the user requests to open a sound file //----------------------------------------------------------------------------- VOID OnOpenSoundFile( HWND hDlg ) { GUID guid3DAlgorithm = GUID_NULL; int nResult; HRESULT hr; static TCHAR strFileName[MAX_PATH] = TEXT(""); static TCHAR strPath[MAX_PATH] = TEXT(""); // Setup the OPENFILENAME structure OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL, TEXT("Wave Files\0*.wav\0All Files\0*.*\0\0"), NULL, 0, 1, strFileName, MAX_PATH, NULL, 0, strPath, TEXT("Open Sound File"), OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0, TEXT(".wav"), 0, NULL, NULL }; // Get the default media path (something like C:\WINDOWS\MEDIA) if( '\0' == strPath[0] ) { GetWindowsDirectory( strPath, MAX_PATH ); if( strcmp( &strPath[strlen(strPath)], TEXT("\\") ) ) strcat( strPath, TEXT("\\") ); strcat( strPath, TEXT("MEDIA") ); } if( g_pSound ) { g_pSound->Stop(); g_pSound->Reset(); } // Update the UI controls to show the sound as loading a file EnableWindow( GetDlgItem( hDlg, IDC_PLAY ), FALSE); EnableWindow( GetDlgItem( hDlg, IDC_STOP ), FALSE); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Loading file...") ); // Stop the timer while dialogs are displayed g_bAllowMovementTimer = FALSE; // Display the OpenFileName dialog. Then, try to load the specified file if( TRUE != GetOpenFileName( &ofn ) ) { SetDlgItemText( hDlg, IDC_STATUS, TEXT("Load aborted.") ); g_bAllowMovementTimer = TRUE; return; } SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); // Free any previous sound, and make a new one SAFE_DELETE( g_pSound ); CWaveFile waveFile; waveFile.Open( strFileName, NULL, WAVEFILE_READ ); WAVEFORMATEX* pwfx = waveFile.GetFormat(); if( pwfx == NULL ) { SetDlgItemText( hDlg, IDC_STATUS, TEXT("Invalid wave file format.") ); return; } if( pwfx->nChannels > 1 ) { // Too many channels in wave. Sound must be mono when using DSBCAPS_CTRL3D SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be mono for 3D control.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; } if( pwfx->wFormatTag != WAVE_FORMAT_PCM ) { // Sound must be PCM when using DSBCAPS_CTRL3D SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be PCM for 3D control.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; } // Get the software DirectSound3D emulation algorithm to use // Ask the user for this sample, so display the algorithm dialog box. nResult = (int)DialogBox( NULL, MAKEINTRESOURCE(IDD_3D_ALGORITHM), NULL, AlgorithmDlgProc ); switch( nResult ) { case -1: // User canceled dialog box SetDlgItemText( hDlg, IDC_STATUS, TEXT("Load aborted.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; case 0: // User selected DS3DALG_NO_VIRTUALIZATION guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION; break; case 1: // User selected DS3DALG_HRTF_FULL guid3DAlgorithm = DS3DALG_HRTF_FULL; break; case 2: // User selected DS3DALG_HRTF_LIGHT guid3DAlgorithm = DS3DALG_HRTF_LIGHT; break; } // Load the wave file into a DirectSound buffer hr = g_pSoundManager->Create( &g_pSound, strFileName, DSBCAPS_CTRL3D, guid3DAlgorithm ); if( FAILED( hr ) || hr == DS_NO_VIRTUALIZATION ) { DXTRACE_ERR_NOMSGBOX( TEXT("Create"), hr ); if( DS_NO_VIRTUALIZATION == hr ) { MessageBox( hDlg, "The 3D virtualization algorithm requested is not supported under this " "operating system. It is available only on Windows 2000, Windows ME, and Windows 98 with WDM " "drivers and beyond. Creating buffer with no virtualization.", "DirectSound Sample", MB_OK ); } // Unknown error, but not a critical failure, so just update the status SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Could not create sound buffer.") ); return; } // Get the 3D buffer from the secondary buffer if( FAILED( hr = g_pSound->Get3DBufferInterface( 0, &g_pDS3DBuffer ) ) ) { DXTRACE_ERR( TEXT("Get3DBufferInterface"), hr ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Could not get 3D buffer.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; } // Get the 3D buffer parameters g_dsBufferParams.dwSize = sizeof(DS3DBUFFER); g_pDS3DBuffer->GetAllParameters( &g_dsBufferParams ); // Set new 3D buffer parameters g_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE; g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE ); DSBCAPS dsbcaps; ZeroMemory( &dsbcaps, sizeof(DSBCAPS) ); dsbcaps.dwSize = sizeof(DSBCAPS); LPDIRECTSOUNDBUFFER pDSB = g_pSound->GetBuffer( 0 ); pDSB->GetCaps( &dsbcaps ); if( ( dsbcaps.dwFlags & DSBCAPS_LOCHARDWARE ) != 0 ) SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded using hardware mixing.") ); else SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded using software mixing.") ); // Update the UI controls to show the sound as the file is loaded SetDlgItemText( hDlg, IDC_FILENAME, strFileName ); EnablePlayUI( hDlg, TRUE ); g_bAllowMovementTimer = TRUE; // Remember the path for next time strcpy( strPath, strFileName ); char* strLastSlash = strrchr( strPath, '\\' ); strLastSlash[0] = '\0'; // Set the slider positions SetSlidersPos( hDlg, 0.0f, 0.0f, ORBIT_MAX_RADIUS, ORBIT_MAX_RADIUS*2.0f ); OnSliderChanged( hDlg ); }
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; } }
//----------------------------------------------------------------------------- // Name: CSoundManager::CreateFromMemory() // Desc: //----------------------------------------------------------------------------- HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNumBuffers ) { HRESULT hr; DWORD i; IDirectSoundBuffer** apDSBuffer = NULL; DWORD dwDSBufferSize = NULL; CWaveFile* pWaveFile = NULL; if( m_pDS == NULL ) return CO_E_NOTINITIALIZED; if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) return E_INVALIDARG; apDSBuffer = new IDirectSoundBuffer*[dwNumBuffers]; if( apDSBuffer == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile = new CWaveFile(); if( pWaveFile == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); // Make the DirectSound buffer the same size as the wav file dwDSBufferSize = ulDataSize; // Create the direct sound buffer, and only request the flags needed // since each requires some overhead and limits if the buffer can // be hardware accelerated DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwCreationFlags; dsbd.dwBufferBytes = dwDSBufferSize; dsbd.guid3DAlgorithm = guid3DAlgorithm; dsbd.lpwfxFormat = pwfx; if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) { DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } // Default to use DuplicateSoundBuffer() when created extra buffers since always // create a buffer that uses the same memory however DuplicateSoundBuffer() will fail if // DSBCAPS_CTRLFX is used, so use CreateSoundBuffer() instead in this case. if( (dwCreationFlags & DSBCAPS_CTRLFX) == 0 ) { for( i=1; i<dwNumBuffers; i++ ) { if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) { DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); goto LFail; } } } else { for( i=1; i<dwNumBuffers; i++ ) { hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL ); if( FAILED(hr) ) { DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } } } // Create the sound *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags ); SAFE_DELETE_ARRAY( apDSBuffer ); return S_OK; LFail: // Cleanup SAFE_DELETE_ARRAY( apDSBuffer ); return hr; }
//-------------------------------------------------------------------------------------- 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; }
HRESULT DemoApp::Initialize() { HRESULT hr; //register window class WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = DemoApp::WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); wcex.hInstance = HINST_THISCOMPONENT; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = NULL; wcex.lpszMenuName = NULL; wcex.lpszClassName = L"App"; RegisterClassEx(&wcex); hr = CreateDeviceIndependentResources(); if (SUCCEEDED(hr)) { // Create the application window. m_hwnd = CreateWindow( L"App", L"달걀 채색 공장(201001622 이진용)", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1200, 600, NULL, NULL, HINST_THISCOMPONENT, this ); hr = m_hwnd ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { float length = 0; hr = m_wheelPath->ComputeLength( NULL, //no transform &length ); if (SUCCEEDED(hr) ) { m_Animation.SetStart(0); //start at beginning of path m_Animation.SetEnd(length); //length at end of path m_Animation.SetDuration(5.f ); //seconds ZeroMemory(&m_DwmTimingInfo, sizeof(m_DwmTimingInfo)); m_DwmTimingInfo.cbSize = sizeof(m_DwmTimingInfo); // Get the composition refresh rate. If the DWM isn't running, // get the refresh rate from GDI -- probably going to be 60Hz if (FAILED(DwmGetCompositionTimingInfo(NULL, &m_DwmTimingInfo))) { HDC hdc = GetDC(m_hwnd); m_DwmTimingInfo.rateCompose.uiDenominator = 1; m_DwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hdc, VREFRESH); ReleaseDC(m_hwnd, hdc); } ShowWindow(m_hwnd, SW_SHOWNORMAL); UpdateWindow(m_hwnd); } } if (SUCCEEDED(hr)) { float pLength = 0; hr = m_flyPath->ComputeLength( NULL, //no transform &pLength ); if (SUCCEEDED(hr) ) { m_linearAnimation.SetStart(0); //start at beginning of path m_linearAnimation.SetEnd(pLength); //length at end of path m_linearAnimation.SetDuration(10.f); //seconds ZeroMemory(&m_DwmTimingInfo, sizeof(m_DwmTimingInfo)); m_DwmTimingInfo.cbSize = sizeof(m_DwmTimingInfo); // Get the composition refresh rate. If the DWM isn't running, // get the refresh rate from GDI -- probably going to be 60Hz if (FAILED(DwmGetCompositionTimingInfo(NULL, &m_DwmTimingInfo))) { HDC hdc = GetDC(m_hwnd); m_DwmTimingInfo.rateCompose.uiDenominator = 1; m_DwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hdc, VREFRESH); ReleaseDC(m_hwnd, hdc); } ShowWindow(m_hwnd, SW_SHOWNORMAL); UpdateWindow(m_hwnd); } } } //장치 객체 생성 IDirectSound8* directSound; DirectSoundCreate8(NULL,&directSound, NULL); //협력레벨 지정 directSound->SetCooperativeLevel(m_hwnd,DSSCL_PRIORITY); //주버퍼 포맷 지정 DSBUFFERDESC dsbd; ZeroMemory(&dsbd,sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; //IDirectSoundBuffer* pDSBPrimary = NULL; directSound->CreateSoundBuffer(&dsbd, &pDSBPrimary, NULL); WAVEFORMATEX wfx; ZeroMemory(&wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = (WORD)WAVE_FORMAT_PCM; wfx.nChannels =(WORD)2; wfx.nSamplesPerSec = (DWORD)22050; wfx.wBitsPerSample = (WORD)16; wfx.nBlockAlign = (WORD)(wfx.wBitsPerSample / 8 * wfx.nChannels ); wfx.nAvgBytesPerSec = (DWORD)(wfx.nSamplesPerSec * wfx.nBlockAlign ); pDSBPrimary->SetFormat(&wfx); pDSBPrimary->Release(); //2차 버퍼 생성 BGM CWaveFile* pWaveFile = NULL; pWaveFile = new CWaveFile(); pWaveFile->Open( L".\\pokemonCenter.wav", NULL, WAVEFILE_READ ); //DSBUFFERDESC dsbd; ZeroMemory(&dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_CTRLVOLUME; dsbd.guid3DAlgorithm = GUID_NULL; dsbd.lpwfxFormat = pWaveFile->m_pwfx; dsbd.dwBufferBytes = pWaveFile->GetSize(); directSound->CreateSoundBuffer(&dsbd, &pDSBuffer, NULL); //이차버퍼에 데이터 채우기 sound = new CSound(&pDSBuffer, dsbd.dwBufferBytes, 1 , pWaveFile, 0 ); // pDSBuffer 위에 전역변수임 pDSBPrimary->SetVolume(scaledVolume); sound->Play(0,DSBPLAY_LOOPING); soundManager = new CSoundManager; if( ! soundManager->init(m_hwnd) ) return FALSE; int id; if (! soundManager->add(L".\\boss.wav", &id)) //id=0부터 시작함. return FALSE; if (! soundManager->add(L".\\storm.wav",&id)); return hr; }
//----------------------------------------------------------------------------- // Name: CSoundManager::CreateStreaming() // Desc: //----------------------------------------------------------------------------- HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ) { HRESULT hr; if( m_pDS == NULL ) return CO_E_NOTINITIALIZED; if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) return E_INVALIDARG; IDirectSoundBuffer* pDSBuffer = NULL; DWORD dwDSBufferSize = NULL; CWaveFile* pWaveFile = NULL; DSBPOSITIONNOTIFY* aPosNotify = NULL; IDirectSoundNotify* pDSNotify = NULL; pWaveFile = new CWaveFile(); if( pWaveFile == NULL ) return E_OUTOFMEMORY; pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); // Figure out how big the DirectSound buffer should be dwDSBufferSize = dwNotifySize * dwNotifyCount; // Set up the direct sound buffer. Request the NOTIFY flag, so // that we are notified as the sound buffer plays. Note, that using this flag // may limit the amount of hardware acceleration that can occur. DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwCreationFlags | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2; dsbd.dwBufferBytes = dwDSBufferSize; dsbd.guid3DAlgorithm = guid3DAlgorithm; dsbd.lpwfxFormat = pWaveFile->m_pwfx; if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) { // If wave format isn't then it will return // either DSERR_BADFORMAT or E_INVALIDARG if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); } // Create the notification events, so that we know when to fill // the buffer as the sound plays. if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, (VOID**)&pDSNotify ) ) ) { SAFE_DELETE_ARRAY( aPosNotify ); return DXTRACE_ERR( TEXT("QueryInterface"), hr ); } aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; if( aPosNotify == NULL ) return E_OUTOFMEMORY; for( DWORD i = 0; i < dwNotifyCount; i++ ) { aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; aPosNotify[i].hEventNotify = hNotifyEvent; } // Tell DirectSound when to notify us. The notification will come in the from // of signaled events that are handled in WinMain() if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, aPosNotify ) ) ) { SAFE_RELEASE( pDSNotify ); SAFE_DELETE_ARRAY( aPosNotify ); return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); } SAFE_RELEASE( pDSNotify ); SAFE_DELETE_ARRAY( aPosNotify ); // Create the sound *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); return S_OK; }
/* 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; }
// export thread static DWORD __stdcall export_rendering_thread(void *parameter) { const int samples_per_sec = 44100; uint progress = 0; WAVEFORMATEX wfxInput; ZeroMemory( &wfxInput, sizeof(wfxInput)); wfxInput.wFormatTag = WAVE_FORMAT_PCM; wfxInput.nSamplesPerSec = samples_per_sec; wfxInput.wBitsPerSample = 16; wfxInput.nChannels = 2; wfxInput.nBlockAlign = wfxInput.nChannels * (wfxInput.wBitsPerSample / 8); wfxInput.nAvgBytesPerSec = wfxInput.nBlockAlign * wfxInput.nSamplesPerSec; HRESULT hr; CWaveFile wavFile; hr = wavFile.Open((char*)parameter, &wfxInput, WAVEFILE_WRITE); if (FAILED(hr)) { goto done; } // stop playing song_stop_playback(); // skip 5 seconds for (int samples = samples_per_sec * 5; samples > 0; samples -= 32) { float temp_buffer[2][32]; // update song song_update(1000.0 * (double)32 / (double)samples_per_sec); // update effect vsti_update_config((float)samples_per_sec, 32); // call vsti process func vsti_process(temp_buffer[0], temp_buffer[1], 32); } song_start_playback(); for (;;) { const int samples = 32; float temp_buffer[2][samples]; short output_buffer[2 * samples]; // update song song_update(1000.0 * (double)samples / (double)samples_per_sec); // update effect vsti_update_config((float)samples_per_sec, samples); // call vsti process func vsti_process(temp_buffer[0], temp_buffer[1], samples); short* output = output_buffer; float volume = config_get_output_volume() / 100.0; for (int i = 0; i < samples; i++) { float l = output[0] = convertSample(temp_buffer[0][i] * 32767.0f * volume); output[1] = convertSample(temp_buffer[1][i] * 32767.0f * volume); output += 2; } UINT sizeWrote = 0; hr = wavFile.Write(sizeof(output_buffer), (BYTE*)output_buffer, &sizeWrote); if (!song_is_playing()) break; if (!gui_is_exporting()) break; uint new_progress = 100 * song_get_time() / song_get_length(); if (new_progress != progress) { progress = new_progress; gui_update_export_progress(progress); } } done: song_stop_playback(); gui_close_export_progress(); wavFile.Close(); return hr; }