//----------------------------------------------------------------------------- // 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 ); } }
//----------------------------------------------------------------------------- // 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 ); }
//----------------------------------------------------------------------------- // Name: OnInitDialog() // Desc: Initializes the dialogs (sets up UI controls, etc.) //----------------------------------------------------------------------------- VOID OnInitDialog( HWND hDlg ) { HRESULT hr; // Load the icon #ifdef _WIN64 HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE ); #else HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE ); #endif HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDR_MAINFRAME ) ); // Create a static IDirectSound in the CSound class. // Set coop level to DSSCL_PRIORITY, and set primary buffer // format to stereo, 22kHz and 16-bit output. g_pSoundManager = new CSoundManager(); hr = g_pSoundManager->Initialize( hDlg, DSSCL_PRIORITY, 2, 22050, 16 ); // Get the 3D listener, so we can control its params hr |= g_pSoundManager->Get3DListenerInterface( &g_pDSListener ); if( FAILED(hr) ) { DXTRACE_ERR( TEXT("Get3DListenerInterface"), hr ); MessageBox( hDlg, "Error initializing DirectSound. Sample will now exit.", "DirectSound Sample", MB_OK | MB_ICONERROR ); EndDialog( hDlg, IDABORT ); return; } // Get listener parameters g_dsListenerParams.dwSize = sizeof(DS3DLISTENER); g_pDSListener->GetAllParameters( &g_dsListenerParams ); // Set the icon for this dialog. PostMessage( hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon ); // Set big icon PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon ); // Set small icon // Create a timer to periodically move the 3D object around SetTimer( hDlg, IDT_MOVEMENT_TIMER, 0, NULL ); // Set the UI controls SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("No file loaded.") ); // Get handles to dialog items HWND hDopplerSlider = GetDlgItem( hDlg, IDC_DOPPLER_SLIDER ); HWND hRolloffSlider = GetDlgItem( hDlg, IDC_ROLLOFF_SLIDER ); HWND hMinDistSlider = GetDlgItem( hDlg, IDC_MINDISTANCE_SLIDER ); HWND hMaxDistSlider = GetDlgItem( hDlg, IDC_MAXDISTANCE_SLIDER ); HWND hVertSlider = GetDlgItem( hDlg, IDC_VERTICAL_SLIDER ); HWND hHorzSlider = GetDlgItem( hDlg, IDC_HORIZONTAL_SLIDER ); // Set the range and position of the sliders PostMessage( hDopplerSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hDopplerSlider, TBM_SETRANGEMIN, TRUE, 0L ); PostMessage( hRolloffSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hRolloffSlider, TBM_SETRANGEMIN, TRUE, 0L ); PostMessage( hMinDistSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hMinDistSlider, TBM_SETRANGEMIN, TRUE, 1L ); PostMessage( hMaxDistSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hMaxDistSlider, TBM_SETRANGEMIN, TRUE, 1L ); PostMessage( hVertSlider, TBM_SETRANGEMAX, TRUE, 100L ); PostMessage( hVertSlider, TBM_SETRANGEMIN, TRUE, -100L ); PostMessage( hVertSlider, TBM_SETPOS, TRUE, 100L ); PostMessage( hHorzSlider, TBM_SETRANGEMAX, TRUE, 100L ); PostMessage( hHorzSlider, TBM_SETRANGEMIN, TRUE, -100L ); PostMessage( hHorzSlider, TBM_SETPOS, TRUE, 100L ); // Set the position of the sliders SetSlidersPos( hDlg, 0.0f, 0.0f, ORBIT_MAX_RADIUS, ORBIT_MAX_RADIUS*2.0f ); }
//----------------------------------------------------------------------------- // Name: OnInitDialog() // Desc: Initializes the dialogs (sets up UI controls, etc.) //----------------------------------------------------------------------------- VOID OnInitDialog( HWND hDlg ) { HRESULT hr; // Load the icon #ifdef _WIN64 HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE ); #else HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE ); #endif HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDR_MAINFRAME ) ); // Create a static IDirectSound in the CSound class. // Set coop level to DSSCL_PRIORITY, and set primary buffer // format to stereo, 22kHz and 16-bit output. g_pSoundManager = new CSoundManager(); if( NULL == g_pSoundManager ) { DXTRACE_ERR_MSGBOX( TEXT("Initialize"), E_OUTOFMEMORY ); EndDialog( hDlg, IDABORT ); return; } if( FAILED( hr = g_pSoundManager->Initialize( hDlg, DSSCL_PRIORITY ) ) ) { DXTRACE_ERR_MSGBOX( TEXT("Initialize"), hr ); MessageBox( hDlg, "Error initializing DirectSound. Sample will now exit.", "DirectSound Sample", MB_OK | MB_ICONERROR ); EndDialog( hDlg, IDABORT ); return; } if( FAILED( hr = g_pSoundManager->SetPrimaryBufferFormat( 2, 22050, 16 ) ) ) { DXTRACE_ERR_MSGBOX( TEXT("SetPrimaryBufferFormat"), hr ); MessageBox( hDlg, "Error initializing DirectSound. Sample will now exit.", "DirectSound Sample", MB_OK | MB_ICONERROR ); EndDialog( hDlg, IDABORT ); return; } // Set the icon for this dialog. PostMessage( hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon ); // Set big icon PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon ); // Set small icon // Create a timer, so we can check for when the soundbuffer is stopped SetTimer( hDlg, 0, 250, NULL ); // Get handles to dialog items HWND hFreqSlider = GetDlgItem( hDlg, IDC_FREQUENCY_SLIDER ); HWND hPanSlider = GetDlgItem( hDlg, IDC_PAN_SLIDER ); HWND hVolumeSlider = GetDlgItem( hDlg, IDC_VOLUME_SLIDER ); // Set the focus to normal by default CheckRadioButton( hDlg, IDC_FOCUS_NORMAL, IDC_FOCUS_NORMAL, IDC_FOCUS_NORMAL ); // Set the buffer mixing to default CheckRadioButton( hDlg, IDC_MIX_DEFAULT, IDC_MIX_SOFTWARE, IDC_MIX_DEFAULT ); // Set the range and position of the freq slider from // DSBFREQUENCY_MIN and DSBFREQUENCY_MAX are DirectSound constants PostMessage( hFreqSlider, TBM_SETRANGEMAX, TRUE, DSBFREQUENCY_MAX ); PostMessage( hFreqSlider, TBM_SETRANGEMIN, TRUE, DSBFREQUENCY_MIN ); // Set the range and position of the pan slider from PostMessage( hPanSlider, TBM_SETRANGEMAX, TRUE, ( 10000L/500L) ); PostMessage( hPanSlider, TBM_SETRANGEMIN, TRUE, (-10000L/500L) ); // Set the range and position of the volume slider PostMessage( hVolumeSlider, TBM_SETRANGEMAX, TRUE, 0L ); PostMessage( hVolumeSlider, TBM_SETRANGEMIN, TRUE, (-5000L/100L) ); // Set the position of the sliders SetSlidersPos( hDlg, DSBFREQUENCY_MIN, 0, 0 ); // Set the UI controls SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("No file loaded.") ); UpdateBehaviorText( hDlg ); }