//----------------------------------------------------------------------------- // 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 ); } }
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; }
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; }
//----------------------------------------------------------------------------- // 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; } }
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; }
//计算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; }
//-------------------------------------------------------------------------------------- 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; }
// 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; }