soundfx.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:46k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #define STRICT
  2. #include <windows.h>
  3. #include "basetsd.h"
  4. #include <mmsystem.h>
  5. #include <mmreg.h>
  6. #include <dxerr9.h>
  7. #include <dsound.h>
  8. #include <cguid.h>
  9. #include <commctrl.h>
  10. #include <commdlg.h>
  11. #include <stdio.h>
  12. #include "DSUtil.h"
  13. #include "resource.h"
  14. #define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
  15. #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
  16. #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
  17. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg,  WPARAM wParam, LPARAM lParam );
  18. VOID    OnInitDialog( HWND hDlg );
  19. VOID    OnTimer( HWND hDlg );
  20. VOID    OnOpenSoundFile( HWND hDlg );
  21. HRESULT OnPlaySound( HWND hDlg );
  22. VOID    OnEffectChanged( HWND hDlg );
  23. HRESULT ValidateWaveFile( HWND hDlg, TCHAR* strFileName );
  24. HRESULT CreateAndFillBuffer( HWND hDlg, DWORD dwCreationFlags );
  25. VOID    SetBufferOptions( LONG lFrequency, LONG lPakn, LONG lVolume );
  26. VOID    EnablePlayUI( HWND hDlg, BOOL bEnable );
  27. VOID    LoadParameterUI ( HWND hDlg, DWORD dwFXType );
  28. VOID    ResetParameterUI ( HWND hDlg );
  29. enum ESFXType
  30. {
  31.     eSFX_chorus = 0,
  32.     eSFX_compressor,
  33.     eSFX_distortion,
  34.     eSFX_echo,
  35.     eSFX_flanger,
  36.     eSFX_gargle,
  37.     eSFX_parameq,
  38.     eSFX_reverb,
  39.     
  40.     eNUM_SFX
  41. };
  42. class CSoundFXManager
  43. {
  44. public:
  45.     CSoundFXManager( );
  46.     ~CSoundFXManager( );
  47. public: 
  48.     HRESULT Initialize ( LPDIRECTSOUNDBUFFER lpDSB, BOOL bLoadDefaultParamValues );
  49.     HRESULT UnInitialize ( );
  50.     HRESULT SetFXEnable( DWORD esfxType );
  51.     HRESULT ActivateFX( );
  52.     HRESULT DisableAllFX( );
  53.     HRESULT LoadCurrentFXParameters( );
  54. public: 
  55.     LPDIRECTSOUNDFXCHORUS8      m_lpChorus;
  56.     LPDIRECTSOUNDFXCOMPRESSOR8  m_lpCompressor;
  57.     LPDIRECTSOUNDFXDISTORTION8  m_lpDistortion;
  58.     LPDIRECTSOUNDFXECHO8        m_lpEcho;
  59.     LPDIRECTSOUNDFXFLANGER8     m_lpFlanger;
  60.     LPDIRECTSOUNDFXGARGLE8      m_lpGargle;
  61.     LPDIRECTSOUNDFXPARAMEQ8     m_lpParamEq;
  62.     LPDIRECTSOUNDFXWAVESREVERB8 m_lpReverb;
  63.     DSFXChorus                  m_paramsChorus;
  64.     DSFXCompressor              m_paramsCompressor;
  65.     DSFXDistortion              m_paramsDistortion;
  66.     DSFXEcho                    m_paramsEcho;
  67.     DSFXFlanger                 m_paramsFlanger;
  68.     DSFXGargle                  m_paramsGargle;
  69.     DSFXParamEq                 m_paramsParamEq;
  70.     DSFXWavesReverb             m_paramsReverb;
  71.     LPDIRECTSOUNDBUFFER8        m_lpDSB8;
  72. protected:
  73.     DSEFFECTDESC                m_rgFxDesc[eNUM_SFX];
  74.     const GUID *                m_rgRefGuids[eNUM_SFX];
  75.     LPVOID *                    m_rgPtrs[eNUM_SFX];
  76.     BOOL                        m_rgLoaded[eNUM_SFX];
  77.     DWORD                       m_dwNumFX;
  78.     HRESULT EnableGenericFX( GUID guidSFXClass, REFGUID rguidInterface, LPVOID * ppObj );
  79.     HRESULT LoadDefaultParamValues( );
  80. };
  81. #define             DEFAULT_SLIDER_MIN          1
  82. #define             DEFAULT_SLIDER_MAX          0x7FFFFF
  83. #define             DEFAULT_SLIDER_INC          DEFAULT_SLIDER_MAX >> 11
  84. CSoundManager *     g_lpSoundManager = NULL;
  85. CSound *            g_lpSound = NULL;
  86. CSoundFXManager *   g_lpFXManager = NULL;
  87. HINSTANCE           g_hInst = NULL;
  88. TCHAR               g_tszFilename[MAX_PATH];
  89. DWORD               g_dwCurrentFXType           = eSFX_chorus;
  90. const TCHAR *       g_tszFXNames[] = { "Chorus", "Compressor", "Distortion", "Echo",
  91.                                        "Flanger", "Gargle", "Param Eq", "Reverb" };
  92. INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, INT nCmdShow )
  93. {
  94.     g_hInst = hInst;
  95.     CoInitialize( NULL );
  96.     
  97.     InitCommonControls();
  98.     
  99.     DialogBox( hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc );
  100.     CoUninitialize();
  101.     return TRUE;
  102. }
  103. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  104. {
  105.     HRESULT hr;
  106.     switch( msg )
  107.     {
  108.         case WM_COMMAND:
  109.             switch( LOWORD(wParam) )
  110.             {
  111.                 case IDOK:
  112.                 case IDCANCEL:
  113.                     EndDialog( hDlg, IDOK );
  114.                     break;
  115.                 case IDC_BUTTON_OPEN:
  116.                     OnOpenSoundFile( hDlg );
  117.                     break;
  118.                 case IDC_BUTTON_PLAY:
  119.                     if( FAILED( hr = OnPlaySound( hDlg ) ) )
  120.                     {
  121.                         DXTRACE_ERR_MSGBOX( TEXT("OnPlaySound"), hr );
  122.                         MessageBox( hDlg, "Error playing DirectSound buffer."
  123.                                     "Sample will now exit.", "DirectSound Sample",
  124.                                     MB_OK | MB_ICONERROR );
  125.                         EndDialog( hDlg, IDABORT );
  126.                     }
  127.                     break;
  128.                 case IDC_BUTTON_STOP:
  129.                     if( g_lpSound )
  130.                     {
  131.                         g_lpSound->Stop();
  132.                         g_lpSound->Reset();
  133.                     }
  134.                     g_lpFXManager->DisableAllFX( );
  135.                     EnablePlayUI( hDlg, TRUE );
  136.                     SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Sound stopped.") );
  137.                     break;
  138.                 case IDC_RADIO_TRIANGLE:
  139.                 case IDC_RADIO_SQUARE:
  140.                 case IDC_RADIO_SINE:
  141.                 case IDC_RADIO_NEG_180:
  142.                 case IDC_RADIO_NEG_90:
  143.                 case IDC_RADIO_ZERO:
  144.                 case IDC_RADIO_90:
  145.                 case IDC_RADIO_180:
  146.                     OnEffectChanged( hDlg );
  147.                     break;
  148.                 default:
  149.                     if( LOWORD( wParam ) >= IDC_RADIO_CHORUS &&
  150.                         LOWORD( wParam ) <= IDC_RADIO_REVERB )
  151.                     {
  152.                         g_dwCurrentFXType = LOWORD( wParam ) - IDC_RADIO_CHORUS;
  153.                         LoadParameterUI( hDlg, g_dwCurrentFXType );
  154.                     }
  155.                     else
  156.                         return FALSE; 
  157.             }
  158.             break;
  159.         case WM_TIMER:
  160.             OnTimer( hDlg );
  161.             break;
  162.         case WM_INITDIALOG:
  163.             OnInitDialog( hDlg );
  164.             break;
  165.         case WM_NOTIFY:
  166.         {
  167.             
  168.             
  169.             
  170.                 OnEffectChanged( hDlg );
  171.             
  172.             break;
  173.         }
  174.         case WM_DESTROY:
  175.             
  176.             KillTimer( hDlg, 1 );
  177.             SAFE_DELETE( g_lpFXManager );
  178.             SAFE_DELETE( g_lpSound );
  179.             SAFE_DELETE( g_lpSoundManager );
  180.             break;
  181.         default:
  182.             return FALSE; 
  183.     }
  184.     return TRUE; 
  185. }
  186. VOID OnInitDialog( HWND hDlg )
  187. {
  188.     HRESULT hr;
  189.     
  190.     HICON hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_ICON ) );
  191.     PostMessage( hDlg, WM_SETICON, ICON_BIG, ( LPARAM ) hIcon );
  192.     PostMessage( hDlg, WM_SETICON, ICON_SMALL, ( LPARAM ) hIcon );
  193.     
  194.     
  195.     
  196.     g_lpSoundManager = new CSoundManager();
  197.     g_lpFXManager = new CSoundFXManager();
  198.     if( NULL == g_lpSoundManager ||
  199.         NULL == g_lpFXManager )
  200.     {
  201.         DXTRACE_ERR_MSGBOX( TEXT("Initialize"), E_OUTOFMEMORY );
  202.         EndDialog( hDlg, IDABORT );
  203.         return;
  204.     }
  205.     if( FAILED( hr = g_lpSoundManager->Initialize( hDlg, DSSCL_PRIORITY ) ) )
  206.     {
  207.         DXTRACE_ERR_MSGBOX( TEXT("Initialize"), hr );
  208.         MessageBox( hDlg, "Error initializing DirectSound.  Sample will now exit.",
  209.                             "DirectSound Sample", MB_OK | MB_ICONERROR );
  210.         EndDialog( hDlg, IDABORT );
  211.         return;
  212.     }
  213.     if( FAILED( hr = g_lpSoundManager->SetPrimaryBufferFormat( 2, 22050, 16 ) ) )
  214.     {
  215.         DXTRACE_ERR_MSGBOX( TEXT("SetPrimaryBufferFormat"), hr );
  216.         MessageBox( hDlg, "Error initializing DirectSound.  Sample will now exit.",
  217.                           "DirectSound Sample", MB_OK | MB_ICONERROR );
  218.         EndDialog( hDlg, IDABORT );
  219.         return;
  220.     }
  221.     
  222.     SetTimer( hDlg, 0, 250, NULL );
  223.     
  224.     TCHAR strFile[MAX_PATH];
  225.     if( GetWindowsDirectory( strFile, MAX_PATH ) == 0 )
  226.         return;
  227.     lstrcat( strFile, "\media\ding.wav" );
  228.     
  229.     if( FAILED( hr = ValidateWaveFile( hDlg, strFile ) ) )
  230.     {
  231.         
  232.         SetDlgItemText( hDlg, IDC_TEXT_FILENAME, TEXT("") );
  233.         SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("No file loaded.") );
  234.         EnableWindow( GetDlgItem( hDlg, IDC_BUTTON_PLAY ), FALSE );
  235.         EnableWindow( GetDlgItem( hDlg, IDC_BUTTON_STOP ), FALSE );
  236.         return;
  237.     }
  238.     if( SUCCEEDED( hr = g_lpSoundManager->Create( &g_lpSound, g_tszFilename,
  239.                                                   DSBCAPS_CTRLFX, GUID_NULL ) ) )
  240.     {
  241.         g_lpFXManager->Initialize( g_lpSound->GetBuffer( 0 ), TRUE );
  242.         
  243.         g_lpFXManager->UnInitialize( );
  244.         SAFE_DELETE( g_lpSound );
  245.     }
  246.     
  247.     CheckDlgButton( hDlg, IDC_CHECK_LOOP, BST_CHECKED );
  248.     CheckRadioButton( hDlg, IDC_RADIO_CHORUS, IDC_RADIO_REVERB, IDC_RADIO_CHORUS );
  249.     LoadParameterUI( hDlg, g_dwCurrentFXType );
  250.     EnablePlayUI( hDlg, TRUE );
  251. }
  252. HRESULT OnPlaySound( HWND hDlg )
  253. {
  254.     HRESULT hr;
  255.     DWORD   dwCreationFlags;
  256.     DWORD   dwLooped;
  257.     DWORD   i;
  258.     BOOL bLooped        = ( IsDlgButtonChecked( hDlg, IDC_CHECK_LOOP ) == BST_CHECKED );
  259.     
  260.     dwCreationFlags = DSBCAPS_CTRLFX;
  261.     
  262.     g_lpFXManager->DisableAllFX( );
  263.     SAFE_DELETE( g_lpSound );
  264.     
  265.     
  266.     
  267.     if( FAILED( hr = g_lpSoundManager->Create( &g_lpSound, g_tszFilename,
  268.                                                dwCreationFlags, GUID_NULL ) ) )
  269.     {
  270.         
  271.         DXTRACE_ERR( TEXT("Create"), hr );
  272.         if( hr == DSERR_BUFFERTOOSMALL )
  273.         {
  274.             
  275.             
  276.             
  277.             SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Wave file is too short (less than 150ms) for effect processing.") );
  278.         }
  279.         else
  280.         {
  281.             SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Could not create sound buffer.") );
  282.         }
  283.         return S_FALSE;
  284.     }
  285.     g_lpFXManager->Initialize( g_lpSound->GetBuffer( 0 ), FALSE );
  286.     for( i = IDC_CHECK_CHORUS; i <= IDC_CHECK_REVERB; i++ )
  287.     {
  288.         if( IsDlgButtonChecked( hDlg, i ) == BST_CHECKED )
  289.             g_lpFXManager->SetFXEnable( i - IDC_CHECK_CHORUS );
  290.     }
  291.     if( FAILED( hr = g_lpFXManager->ActivateFX( ) ) )
  292.         goto LFail;
  293.     if( FAILED( hr = g_lpFXManager->LoadCurrentFXParameters( ) ) )
  294.         goto LFail;
  295.     
  296.     dwLooped = bLooped ? DSBPLAY_LOOPING : 0L;
  297.     if( FAILED( hr = g_lpSound->Play( 0, dwLooped ) ) )
  298.         return DXTRACE_ERR( TEXT("Play"), hr );
  299.     
  300.     EnablePlayUI( hDlg, FALSE );
  301.     SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Sound playing.") );
  302.     return S_OK;
  303. LFail:
  304.     
  305.     SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Effects creation failed.  Some effects may not support 8-bit wave files.") );
  306.     return S_OK;
  307. }
  308. VOID OnOpenSoundFile( HWND hDlg )
  309. {
  310.     static TCHAR strFileName[MAX_PATH] = TEXT("");
  311.     static TCHAR strPath[MAX_PATH] = TEXT("");
  312.     
  313.     OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL,
  314.                          TEXT("Wave Files*.wavAll Files*.*"), NULL,
  315.                          0, 1, strFileName, MAX_PATH, NULL, 0, strPath,
  316.                          TEXT("Open Sound File"),
  317.                          OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0,
  318.                          TEXT(".wav"), 0, NULL, NULL };
  319.     
  320.     if( '' == strPath[0] )
  321.     {
  322.         if( GetWindowsDirectory( strPath, MAX_PATH ) != 0 )
  323.         {
  324.             if( strcmp( &strPath[strlen(strPath)], TEXT("\") ) )
  325.                 strcat( strPath, TEXT("\") );
  326.             strcat( strPath, TEXT("MEDIA") );
  327.         }
  328.     }
  329.     
  330.    
  331.    
  332.     SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Loading file...") );
  333.     
  334.     g_lpFXManager->DisableAllFX( );
  335.     
  336.     if( TRUE != GetOpenFileName( &ofn ) )
  337.     {
  338.         
  339.         SetDlgItemText( hDlg, IDC_TEXT_FILENAME, TEXT("") );
  340.         SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("No file loaded.") );
  341.       
  342.       
  343.         return;
  344.     }
  345.     SetDlgItemText( hDlg, IDC_TEXT_FILENAME, TEXT("") );
  346.     
  347.     if( FAILED( ValidateWaveFile( hDlg, strFileName ) ) )
  348.     {
  349.         
  350.         SetDlgItemText( hDlg, IDC_TEXT_FILENAME, TEXT("") );
  351.        
  352.        
  353.         return;
  354.     }
  355.     EnablePlayUI( hDlg, TRUE );
  356.     
  357.     strcpy( strPath, strFileName );
  358.     char* strLastSlash = strrchr( strPath, '\' );
  359.     if( strLastSlash )
  360.         strLastSlash[0] = '';
  361. }
  362. VOID OnTimer( HWND hDlg )
  363. {
  364.     if( IsWindowEnabled( GetDlgItem( hDlg, IDC_BUTTON_STOP ) ) )
  365.     {
  366.         
  367.         if( g_lpSound && !g_lpSound->IsSoundPlaying() )
  368.         {
  369.             
  370.             EnablePlayUI( hDlg, TRUE );
  371.             SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Sound stopped.") );
  372.         }
  373.     }
  374. }
  375. VOID EnablePlayUI( HWND hDlg, BOOL bEnable )
  376. {
  377.     if( bEnable )
  378.     {
  379.         EnableWindow( GetDlgItem( hDlg, IDC_CHECK_LOOP      ), TRUE );
  380.         EnableWindow( GetDlgItem( hDlg, IDC_BUTTON_PLAY     ), TRUE );
  381.         EnableWindow( GetDlgItem( hDlg, IDC_BUTTON_STOP     ), FALSE );
  382.         SetFocus(     GetDlgItem( hDlg, IDC_BUTTON_PLAY )   );
  383.     }
  384.     else
  385.     {
  386.         EnableWindow( GetDlgItem( hDlg, IDC_CHECK_LOOP      ), FALSE );
  387.         EnableWindow( GetDlgItem( hDlg, IDC_BUTTON_PLAY     ), FALSE );
  388.         EnableWindow( GetDlgItem( hDlg, IDC_BUTTON_STOP     ), TRUE );
  389.         SetFocus(     GetDlgItem( hDlg, IDC_BUTTON_STOP )   );
  390.     }
  391.     for( DWORD i = IDC_CHECK_CHORUS; i <= IDC_CHECK_REVERB; i++ )
  392.         EnableWindow( GetDlgItem( hDlg, i ), bEnable );
  393. }
  394. VOID ResetParameterUI( HWND hwndDlg )
  395. {
  396.     HWND hwndItem;
  397.     DWORD i;
  398.     for ( i = IDC_PARAM_NAME1; i <= IDC_PARAM_MAX6; i++ )
  399.     {
  400.         hwndItem = GetDlgItem( hwndDlg, i );
  401.         SendMessage( hwndItem, WM_SETTEXT, 0, ( LPARAM ) TEXT( "- - -" ) );
  402.         EnableWindow( hwndItem, FALSE );
  403.     }
  404.     for ( i = IDC_SLIDER1; i <= IDC_SLIDER6; i += 5 )
  405.     {
  406.         PostMessage( GetDlgItem( hwndDlg, i ), TBM_SETRANGEMIN, FALSE, DEFAULT_SLIDER_MIN );
  407.         PostMessage( GetDlgItem( hwndDlg, i ), TBM_SETRANGEMAX, FALSE, DEFAULT_SLIDER_MAX );
  408.         PostMessage( GetDlgItem( hwndDlg, i ), TBM_SETLINESIZE, FALSE, DEFAULT_SLIDER_INC );
  409.         PostMessage( GetDlgItem( hwndDlg, i ), TBM_SETPOS, TRUE, 0 );
  410.     }
  411.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_TRIANGLE ), FALSE );
  412.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_SQUARE ), FALSE );
  413.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_SINE ), FALSE );
  414.     EnableWindow( GetDlgItem( hwndDlg, IDC_FRAME_WAVEFORM ), FALSE );
  415.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_NEG_180 ), FALSE );
  416.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_NEG_90 ), FALSE );
  417.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_ZERO ), FALSE );
  418.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_90 ), FALSE );
  419.     EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_180 ), FALSE );
  420.     EnableWindow( GetDlgItem( hwndDlg, IDC_FRAME_PHASE ), FALSE );
  421. }
  422. VOID EnableSingleParameter( HWND hwndDlg, DWORD resID )
  423. {
  424.     for ( DWORD i = resID; i < resID + 5; i++ )
  425.         EnableWindow( GetDlgItem( hwndDlg, i ), TRUE );
  426. }
  427. VOID PosSlider( HWND hwndDlg, DWORD dwSlider, FLOAT val, FLOAT min, FLOAT max,
  428.                 FLOAT fSliderInc )
  429. {
  430.     HWND hwndSlider = GetDlgItem( hwndDlg, dwSlider );
  431.     LONG lSliderInc = (LONG) ( (fSliderInc / (max - min)) * DEFAULT_SLIDER_MAX );
  432.     PostMessage( hwndSlider, TBM_SETLINESIZE, FALSE, lSliderInc );
  433.     FLOAT res = ( val - min ) / ( max - min );
  434.     if( res < 0.0f )
  435.         res = 0.0f;
  436.     else if( res > 1.0f )
  437.         res = 1.0f;
  438.     LONG pos = (LONG) ( res * DEFAULT_SLIDER_MAX );
  439.     PostMessage( hwndSlider, TBM_SETPOS, TRUE, pos );
  440. }
  441. VOID LoadSingleParameter( HWND hwndDlg, DWORD id, const TCHAR * tszName, FLOAT val,
  442.                           FLOAT min, FLOAT max, FLOAT fSliderInc = 0.1f,
  443.                           DWORD dwPrecision = 1 )
  444. {
  445.     TCHAR tszstr[MAX_PATH];
  446.     
  447.     EnableSingleParameter( hwndDlg, id );
  448.     SendMessage( GetDlgItem( hwndDlg, id ), WM_SETTEXT, 0, ( LPARAM ) tszName );
  449.     switch( dwPrecision )
  450.     {
  451.         case 0:
  452.             sprintf( tszstr, "%.0f", val );
  453.             SendMessage( GetDlgItem( hwndDlg, id + 1 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  454.             sprintf( tszstr, "%.0f", min );
  455.             SendMessage( GetDlgItem( hwndDlg, id + 3 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  456.             sprintf( tszstr, "%.0f", max );
  457.             SendMessage( GetDlgItem( hwndDlg, id + 4 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  458.             break;
  459.         case 1:
  460.             sprintf( tszstr, "%.1f", val );
  461.             SendMessage( GetDlgItem( hwndDlg, id + 1 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  462.             sprintf( tszstr, "%.1f", min );
  463.             SendMessage( GetDlgItem( hwndDlg, id + 3 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  464.             sprintf( tszstr, "%.1f", max );
  465.             SendMessage( GetDlgItem( hwndDlg, id + 4 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  466.             break;
  467.         default:
  468.         case 2:
  469.             sprintf( tszstr, "%.2f", val );
  470.             SendMessage( GetDlgItem( hwndDlg, id + 1 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  471.             sprintf( tszstr, "%.2f", min );
  472.             SendMessage( GetDlgItem( hwndDlg, id + 3 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  473.             sprintf( tszstr, "%.2f", max );
  474.             SendMessage( GetDlgItem( hwndDlg, id + 4 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  475.             break;
  476.     }
  477.     PosSlider( hwndDlg, id + 2, val, min, max, fSliderInc );
  478. }
  479. VOID SaveSingleParameter( HWND hwndDlg, DWORD id, FLOAT * val, FLOAT min, FLOAT max, DWORD dwPrecision = 1 )
  480. {
  481.     TCHAR tszstr[MAX_PATH];
  482.     DWORD pos = ( DWORD ) SendMessage( GetDlgItem( hwndDlg, id + 2), TBM_GETPOS, 0, 0 );
  483.     FLOAT percent = ( FLOAT ) ( pos - DEFAULT_SLIDER_MIN ) / ( FLOAT ) ( DEFAULT_SLIDER_MAX - DEFAULT_SLIDER_MIN );
  484.     *val = percent * ( max - min ) + min;
  485.     switch( dwPrecision )
  486.     {
  487.         case 0:
  488.             sprintf( tszstr, "%.0f", *val );
  489.             break;
  490.         case 1:
  491.             sprintf( tszstr, "%.1f", *val );
  492.             break;
  493.         case 2:
  494.         default:
  495.             sprintf( tszstr, "%.2f", *val );
  496.             break;
  497.     }
  498.     SendMessage( GetDlgItem( hwndDlg, id + 1 ), WM_SETTEXT, 0, ( LPARAM ) tszstr );
  499. }
  500. VOID LoadWaveformRadio( HWND hwndDlg, LONG waveform, LONG triangle, LONG square, LONG sine )
  501. {
  502.     if( waveform == triangle )
  503.         CheckRadioButton( hwndDlg, IDC_RADIO_TRIANGLE, IDC_RADIO_SINE, IDC_RADIO_TRIANGLE );
  504.     else if( waveform == square )
  505.         CheckRadioButton( hwndDlg, IDC_RADIO_TRIANGLE, IDC_RADIO_SINE, IDC_RADIO_SQUARE );
  506.     else if( waveform == sine )
  507.         CheckRadioButton( hwndDlg, IDC_RADIO_TRIANGLE, IDC_RADIO_SINE, IDC_RADIO_SINE );
  508.     if( triangle >= 0 )
  509.         EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_TRIANGLE ), TRUE );
  510.     if( square >= 0 )
  511.         EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_SQUARE ), TRUE );
  512.     if( sine >= 0 )
  513.         EnableWindow( GetDlgItem( hwndDlg, IDC_RADIO_SINE ), TRUE );
  514.     EnableWindow( GetDlgItem( hwndDlg, IDC_FRAME_WAVEFORM ), ( triangle + square + sine != -3 ) );
  515. }
  516. VOID LoadPhaseRadio( HWND hwndDlg, LONG phase, LONG neg180, LONG neg90, LONG zero, LONG pos90, LONG pos180 )
  517. {
  518.     for( int i = IDC_RADIO_NEG_180; i <= IDC_RADIO_180; i++ )
  519.         EnableWindow( GetDlgItem( hwndDlg, i ), TRUE );
  520.     EnableWindow( GetDlgItem( hwndDlg, IDC_FRAME_PHASE), TRUE );
  521.     if( phase == neg180 )
  522.         CheckRadioButton( hwndDlg, IDC_RADIO_NEG_180, IDC_RADIO_90, IDC_RADIO_NEG_180 );
  523.     else if( phase == neg90 )
  524.         CheckRadioButton( hwndDlg, IDC_RADIO_NEG_180, IDC_RADIO_90, IDC_RADIO_NEG_90 );
  525.     else if( phase == zero )
  526.         CheckRadioButton( hwndDlg, IDC_RADIO_NEG_180, IDC_RADIO_90, IDC_RADIO_ZERO );
  527.     else if( phase == pos90 )
  528.         CheckRadioButton( hwndDlg, IDC_RADIO_NEG_180, IDC_RADIO_90, IDC_RADIO_90 );
  529.     else if( phase == pos180 )
  530.         CheckRadioButton( hwndDlg, IDC_RADIO_NEG_180, IDC_RADIO_90, IDC_RADIO_180 );
  531. }
  532. VOID LoadParameterUI( HWND hwndDlg, DWORD dwFXType )
  533. {
  534.     TCHAR tszstr[MAX_PATH];
  535.     
  536.     ResetParameterUI( hwndDlg );
  537.     sprintf( tszstr, "修改[%s]音效的参数", g_tszFXNames[dwFXType] );
  538.     SetDlgItemText( hwndDlg, IDC_FRAME, tszstr );
  539.     switch( dwFXType)
  540.     {
  541.         case eSFX_chorus:
  542.         {
  543.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "Wet/Dry Mix (%)" ), g_lpFXManager->m_paramsChorus.fWetDryMix, DSFXCHORUS_WETDRYMIX_MIN, DSFXCHORUS_WETDRYMIX_MAX );
  544.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME2, TEXT( "Depth (%)" ), g_lpFXManager->m_paramsChorus.fDepth, DSFXCHORUS_DEPTH_MIN, DSFXCHORUS_DEPTH_MAX );
  545.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME3, TEXT( "Feedback (%)" ), g_lpFXManager->m_paramsChorus.fFeedback, DSFXCHORUS_FEEDBACK_MIN, DSFXCHORUS_FEEDBACK_MAX );
  546.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME4, TEXT( "Frequency (Hz)" ), g_lpFXManager->m_paramsChorus.fFrequency, DSFXCHORUS_FREQUENCY_MIN, DSFXCHORUS_FREQUENCY_MAX );
  547.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME5, TEXT( "Delay (ms)" ), g_lpFXManager->m_paramsChorus.fDelay, DSFXCHORUS_DELAY_MIN, DSFXCHORUS_DELAY_MAX );
  548.             LoadWaveformRadio( hwndDlg, g_lpFXManager->m_paramsChorus.lWaveform, DSFXCHORUS_WAVE_TRIANGLE, -1, DSFXCHORUS_WAVE_SIN );
  549.             LoadPhaseRadio( hwndDlg, g_lpFXManager->m_paramsChorus.lPhase, DSFXCHORUS_PHASE_NEG_180, DSFXCHORUS_PHASE_NEG_90, DSFXCHORUS_PHASE_ZERO, DSFXCHORUS_PHASE_90, DSFXCHORUS_PHASE_180 );
  550.             break;
  551.         }
  552.         case eSFX_compressor:
  553.         {
  554.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "Gain (dB)" ), g_lpFXManager->m_paramsCompressor.fGain, DSFXCOMPRESSOR_GAIN_MIN, DSFXCOMPRESSOR_GAIN_MAX );
  555.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME2, TEXT( "Attack (ms)" ), g_lpFXManager->m_paramsCompressor.fAttack, DSFXCOMPRESSOR_ATTACK_MIN, DSFXCOMPRESSOR_ATTACK_MAX );
  556.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME3, TEXT( "Release (ms)" ), g_lpFXManager->m_paramsCompressor.fRelease, DSFXCOMPRESSOR_RELEASE_MIN, DSFXCOMPRESSOR_RELEASE_MAX );
  557.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME4, TEXT( "Threshold (dB)" ), g_lpFXManager->m_paramsCompressor.fThreshold, DSFXCOMPRESSOR_THRESHOLD_MIN, DSFXCOMPRESSOR_THRESHOLD_MAX );
  558.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME5, TEXT( "Ratio (x:1)" ), g_lpFXManager->m_paramsCompressor.fRatio, DSFXCOMPRESSOR_RATIO_MIN, DSFXCOMPRESSOR_RATIO_MAX );
  559.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME6, TEXT( "Predelay (ms)" ), g_lpFXManager->m_paramsCompressor.fPredelay, DSFXCOMPRESSOR_PREDELAY_MIN, DSFXCOMPRESSOR_PREDELAY_MAX, 0.05f, 2 );
  560.             break;
  561.         }
  562.         case eSFX_distortion:
  563.         {
  564.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "Gain (dB)" ), g_lpFXManager->m_paramsDistortion.fGain, DSFXDISTORTION_GAIN_MIN, DSFXDISTORTION_GAIN_MAX );
  565.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME2, TEXT( "Edge (%)" ), g_lpFXManager->m_paramsDistortion.fEdge, DSFXDISTORTION_EDGE_MIN, DSFXDISTORTION_EDGE_MAX );
  566.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME3, TEXT( "PostEQ Center Freq (Hz)" ), g_lpFXManager->m_paramsDistortion.fPostEQCenterFrequency, DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN, DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX, 1.0f, 0 );
  567.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME4, TEXT( "PostEQ Bandwidth (Hz)" ), g_lpFXManager->m_paramsDistortion.fPostEQBandwidth, DSFXDISTORTION_POSTEQBANDWIDTH_MIN, DSFXDISTORTION_POSTEQBANDWIDTH_MAX, 1.0f, 0 );
  568.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME5, TEXT( "PreLowpass Cutoff (Hz)" ), g_lpFXManager->m_paramsDistortion.fPreLowpassCutoff, DSFXDISTORTION_PRELOWPASSCUTOFF_MIN, DSFXDISTORTION_PRELOWPASSCUTOFF_MAX, 1.0f, 0 );
  569.             break;
  570.         }
  571.         case eSFX_echo:
  572.         {
  573.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "Wet/Dry Mix (%)" ), g_lpFXManager->m_paramsEcho.fWetDryMix, DSFXECHO_WETDRYMIX_MIN, DSFXECHO_WETDRYMIX_MAX );
  574.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME2, TEXT( "Feedback (%)" ), g_lpFXManager->m_paramsEcho.fFeedback, DSFXECHO_FEEDBACK_MIN, DSFXECHO_FEEDBACK_MAX );
  575.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME3, TEXT( "Left Delay (ms)" ), g_lpFXManager->m_paramsEcho.fLeftDelay, DSFXECHO_LEFTDELAY_MIN, DSFXECHO_LEFTDELAY_MAX );
  576.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME4, TEXT( "Right Delay (ms)" ), g_lpFXManager->m_paramsEcho.fRightDelay, DSFXECHO_RIGHTDELAY_MIN, DSFXECHO_RIGHTDELAY_MAX );
  577.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME5, TEXT( "Pan Delay (bool)" ), (float) g_lpFXManager->m_paramsEcho.lPanDelay, DSFXECHO_PANDELAY_MIN, DSFXECHO_PANDELAY_MAX );
  578.             break;
  579.         }
  580.         case eSFX_flanger:
  581.         {
  582.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "Wet/Dry Mix (%)" ), g_lpFXManager->m_paramsFlanger.fWetDryMix, DSFXFLANGER_WETDRYMIX_MIN, DSFXFLANGER_WETDRYMIX_MAX );
  583.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME2, TEXT( "Depth (%)" ), g_lpFXManager->m_paramsFlanger.fDepth, DSFXFLANGER_DEPTH_MIN, DSFXFLANGER_DEPTH_MAX );
  584.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME3, TEXT( "Feedback (%)" ), g_lpFXManager->m_paramsFlanger.fFeedback, DSFXFLANGER_FEEDBACK_MIN, DSFXFLANGER_FEEDBACK_MAX );
  585.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME4, TEXT( "Frequency (Hz)" ), g_lpFXManager->m_paramsFlanger.fFrequency, DSFXFLANGER_FREQUENCY_MIN, DSFXFLANGER_FREQUENCY_MAX, 0.01f, 2 );
  586.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME5, TEXT( "Delay (ms)" ), g_lpFXManager->m_paramsFlanger.fDelay, DSFXFLANGER_DELAY_MIN, DSFXFLANGER_DELAY_MAX, 0.01f, 2 );
  587.             LoadWaveformRadio( hwndDlg, g_lpFXManager->m_paramsFlanger.lWaveform, DSFXFLANGER_WAVE_TRIANGLE, -1, DSFXFLANGER_WAVE_SIN );
  588.             LoadPhaseRadio( hwndDlg, g_lpFXManager->m_paramsFlanger.lPhase, DSFXFLANGER_PHASE_NEG_180, DSFXFLANGER_PHASE_NEG_90, DSFXFLANGER_PHASE_ZERO, DSFXFLANGER_PHASE_90, DSFXFLANGER_PHASE_180 );
  589.             break;
  590.         }
  591.         case eSFX_gargle:
  592.         {
  593.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "Rate (Hz)" ), ( FLOAT ) g_lpFXManager->m_paramsGargle.dwRateHz, ( FLOAT ) DSFXGARGLE_RATEHZ_MIN, ( FLOAT ) DSFXGARGLE_RATEHZ_MAX );
  594.             LoadWaveformRadio( hwndDlg, g_lpFXManager->m_paramsGargle.dwWaveShape, DSFXGARGLE_WAVE_TRIANGLE, DSFXGARGLE_WAVE_SQUARE, -1 );
  595.             break;
  596.         }
  597.         case eSFX_parameq:
  598.         {
  599.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "Center Freq (Hz)" ), g_lpFXManager->m_paramsParamEq.fCenter, DSFXPARAMEQ_CENTER_MIN, DSFXPARAMEQ_CENTER_MAX );
  600.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME2, TEXT( "Bandwidth (Hz)" ), g_lpFXManager->m_paramsParamEq.fBandwidth, DSFXPARAMEQ_BANDWIDTH_MIN, DSFXPARAMEQ_BANDWIDTH_MAX );
  601.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME3, TEXT( "Gain (dB)" ), g_lpFXManager->m_paramsParamEq.fGain, DSFXPARAMEQ_GAIN_MIN, DSFXPARAMEQ_GAIN_MAX );
  602.             break;
  603.         }
  604.         case eSFX_reverb:
  605.         {
  606.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME1, TEXT( "In Gain (dB)" ), g_lpFXManager->m_paramsReverb.fInGain, DSFX_WAVESREVERB_INGAIN_MIN, DSFX_WAVESREVERB_INGAIN_MAX );
  607.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME2, TEXT( "Reverb Mix (dB)" ), g_lpFXManager->m_paramsReverb.fReverbMix, DSFX_WAVESREVERB_REVERBMIX_MIN, DSFX_WAVESREVERB_REVERBMIX_MAX );
  608.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME3, TEXT( "Reverb Time (ms)" ), g_lpFXManager->m_paramsReverb.fReverbTime, DSFX_WAVESREVERB_REVERBTIME_MIN, DSFX_WAVESREVERB_REVERBTIME_MAX );
  609.             LoadSingleParameter( hwndDlg, IDC_PARAM_NAME4, TEXT( "HighFreq RT Ratio (x:1)" ), g_lpFXManager->m_paramsReverb.fHighFreqRTRatio, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX, 0.01f, 2 );
  610.             break;
  611.         }
  612.     }
  613. }
  614. VOID OnEffectChanged( HWND hwndDlg )
  615. {
  616.     switch( g_dwCurrentFXType )
  617.     {
  618.         case eSFX_chorus:
  619.         {
  620.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &g_lpFXManager->m_paramsChorus.fWetDryMix, DSFXCHORUS_WETDRYMIX_MIN, DSFXCHORUS_WETDRYMIX_MAX );
  621.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME2, &g_lpFXManager->m_paramsChorus.fDepth, DSFXCHORUS_DEPTH_MIN, DSFXCHORUS_DEPTH_MAX );
  622.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME3, &g_lpFXManager->m_paramsChorus.fFeedback, DSFXCHORUS_FEEDBACK_MIN, DSFXCHORUS_FEEDBACK_MAX );
  623.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME4, &g_lpFXManager->m_paramsChorus.fFrequency, DSFXCHORUS_FREQUENCY_MIN, DSFXCHORUS_FREQUENCY_MAX );
  624.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME5, &g_lpFXManager->m_paramsChorus.fDelay, DSFXCHORUS_DELAY_MIN, DSFXCHORUS_DELAY_MAX );
  625.             if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_TRIANGLE ) == BST_CHECKED )
  626.                 g_lpFXManager->m_paramsChorus.lWaveform = DSFXCHORUS_WAVE_TRIANGLE;
  627.             else
  628.                 g_lpFXManager->m_paramsChorus.lWaveform = DSFXCHORUS_WAVE_SIN;
  629.             if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_NEG_180 ) == BST_CHECKED )
  630.                 g_lpFXManager->m_paramsChorus.lPhase = DSFXCHORUS_PHASE_NEG_180;
  631.             else if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_NEG_90 ) == BST_CHECKED )
  632.                 g_lpFXManager->m_paramsChorus.lPhase = DSFXCHORUS_PHASE_NEG_90;
  633.             else if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_ZERO ) == BST_CHECKED )
  634.                 g_lpFXManager->m_paramsChorus.lPhase = DSFXCHORUS_PHASE_ZERO;
  635.             else if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_90 ) == BST_CHECKED )
  636.                 g_lpFXManager->m_paramsChorus.lPhase = DSFXCHORUS_PHASE_90;
  637.             else
  638.                 g_lpFXManager->m_paramsChorus.lPhase = DSFXCHORUS_PHASE_180;
  639.             if( g_lpFXManager->m_lpChorus )
  640.                 g_lpFXManager->m_lpChorus->SetAllParameters( &g_lpFXManager->m_paramsChorus );
  641.             break;
  642.         }
  643.         case eSFX_compressor:
  644.         {
  645.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &g_lpFXManager->m_paramsCompressor.fGain, DSFXCOMPRESSOR_GAIN_MIN, DSFXCOMPRESSOR_GAIN_MAX );
  646.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME2, &g_lpFXManager->m_paramsCompressor.fAttack, DSFXCOMPRESSOR_ATTACK_MIN, DSFXCOMPRESSOR_ATTACK_MAX );
  647.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME3, &g_lpFXManager->m_paramsCompressor.fRelease, DSFXCOMPRESSOR_RELEASE_MIN, DSFXCOMPRESSOR_RELEASE_MAX );
  648.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME4, &g_lpFXManager->m_paramsCompressor.fThreshold, DSFXCOMPRESSOR_THRESHOLD_MIN, DSFXCOMPRESSOR_THRESHOLD_MAX );
  649.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME5, &g_lpFXManager->m_paramsCompressor.fRatio, DSFXCOMPRESSOR_RATIO_MIN, DSFXCOMPRESSOR_RATIO_MAX );
  650.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME6, &g_lpFXManager->m_paramsCompressor.fPredelay, DSFXCOMPRESSOR_PREDELAY_MIN, DSFXCOMPRESSOR_PREDELAY_MAX, 2 );
  651.             if( g_lpFXManager->m_lpCompressor )
  652.                 g_lpFXManager->m_lpCompressor->SetAllParameters( &g_lpFXManager->m_paramsCompressor );
  653.             break;
  654.         }
  655.         case eSFX_distortion:
  656.         {
  657.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &g_lpFXManager->m_paramsDistortion.fGain, DSFXDISTORTION_GAIN_MIN, DSFXDISTORTION_GAIN_MAX );
  658.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME2, &g_lpFXManager->m_paramsDistortion.fEdge, DSFXDISTORTION_EDGE_MIN, DSFXDISTORTION_EDGE_MAX );
  659.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME3, &g_lpFXManager->m_paramsDistortion.fPostEQCenterFrequency, DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN, DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX, 0 );
  660.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME4, &g_lpFXManager->m_paramsDistortion.fPostEQBandwidth, DSFXDISTORTION_POSTEQBANDWIDTH_MIN, DSFXDISTORTION_POSTEQBANDWIDTH_MAX, 0 );
  661.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME5, &g_lpFXManager->m_paramsDistortion.fPreLowpassCutoff, DSFXDISTORTION_PRELOWPASSCUTOFF_MIN, DSFXDISTORTION_PRELOWPASSCUTOFF_MAX, 0 );
  662.             if( g_lpFXManager->m_lpDistortion )
  663.                 g_lpFXManager->m_lpDistortion->SetAllParameters( &g_lpFXManager->m_paramsDistortion );
  664.             break;
  665.         }
  666.         case eSFX_echo:
  667.         {
  668.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &g_lpFXManager->m_paramsEcho.fWetDryMix, DSFXECHO_WETDRYMIX_MIN, DSFXECHO_WETDRYMIX_MAX );
  669.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME2, &g_lpFXManager->m_paramsEcho.fFeedback, DSFXECHO_FEEDBACK_MIN, DSFXECHO_FEEDBACK_MAX );
  670.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME3, &g_lpFXManager->m_paramsEcho.fLeftDelay, DSFXECHO_LEFTDELAY_MIN, DSFXECHO_LEFTDELAY_MAX );
  671.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME4, &g_lpFXManager->m_paramsEcho.fRightDelay, DSFXECHO_RIGHTDELAY_MIN, DSFXECHO_RIGHTDELAY_MAX );
  672.             float fTemp;
  673.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME5, &fTemp, DSFXECHO_PANDELAY_MIN, DSFXECHO_PANDELAY_MAX );
  674.             g_lpFXManager->m_paramsEcho.lPanDelay = (LONG) fTemp;
  675.             if( g_lpFXManager->m_lpEcho )
  676.                 g_lpFXManager->m_lpEcho->SetAllParameters( &g_lpFXManager->m_paramsEcho );
  677.             break;
  678.         }
  679.         case eSFX_flanger:
  680.         {
  681.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &g_lpFXManager->m_paramsFlanger.fWetDryMix, DSFXFLANGER_WETDRYMIX_MIN, DSFXFLANGER_WETDRYMIX_MAX );
  682.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME2, &g_lpFXManager->m_paramsFlanger.fDepth, DSFXFLANGER_DEPTH_MIN, DSFXFLANGER_DEPTH_MAX );
  683.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME3, &g_lpFXManager->m_paramsFlanger.fFeedback, DSFXFLANGER_FEEDBACK_MIN, DSFXFLANGER_FEEDBACK_MAX );
  684.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME4, &g_lpFXManager->m_paramsFlanger.fFrequency, DSFXFLANGER_FREQUENCY_MIN, DSFXFLANGER_FREQUENCY_MAX, 2 );
  685.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME5, &g_lpFXManager->m_paramsFlanger.fDelay, DSFXFLANGER_DELAY_MIN, DSFXFLANGER_DELAY_MAX, 2 );
  686.             if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_TRIANGLE ) == BST_CHECKED )
  687.                 g_lpFXManager->m_paramsFlanger.lWaveform = DSFXFLANGER_WAVE_TRIANGLE;
  688.             else
  689.                 g_lpFXManager->m_paramsFlanger.lWaveform = DSFXFLANGER_WAVE_SIN;
  690.             if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_NEG_180 ) == BST_CHECKED )
  691.                 g_lpFXManager->m_paramsFlanger.lPhase = DSFXFLANGER_PHASE_NEG_180;
  692.             else if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_NEG_90 ) == BST_CHECKED )
  693.                 g_lpFXManager->m_paramsFlanger.lPhase = DSFXFLANGER_PHASE_NEG_90;
  694.             else if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_ZERO ) == BST_CHECKED )
  695.                 g_lpFXManager->m_paramsFlanger.lPhase = DSFXFLANGER_PHASE_ZERO;
  696.             else if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_90 ) == BST_CHECKED )
  697.                 g_lpFXManager->m_paramsFlanger.lPhase = DSFXFLANGER_PHASE_90;
  698.             else
  699.                 g_lpFXManager->m_paramsFlanger.lPhase = DSFXFLANGER_PHASE_180;
  700.             if( g_lpFXManager->m_lpFlanger )
  701.                 g_lpFXManager->m_lpFlanger->SetAllParameters( &g_lpFXManager->m_paramsFlanger );
  702.             break;
  703.         }
  704.         case eSFX_gargle:
  705.         {
  706.             FLOAT fRateHz;
  707.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &fRateHz, DSFXGARGLE_RATEHZ_MIN, DSFXGARGLE_RATEHZ_MAX );
  708.             g_lpFXManager->m_paramsGargle.dwRateHz = (DWORD) fRateHz;
  709.             if( IsDlgButtonChecked( hwndDlg, IDC_RADIO_TRIANGLE ) == BST_CHECKED )
  710.                 g_lpFXManager->m_paramsGargle.dwWaveShape = DSFXGARGLE_WAVE_TRIANGLE;
  711.             else
  712.                 g_lpFXManager->m_paramsGargle.dwWaveShape = DSFXGARGLE_WAVE_SQUARE;
  713.             if( g_lpFXManager->m_lpGargle )
  714.                 g_lpFXManager->m_lpGargle->SetAllParameters( &g_lpFXManager->m_paramsGargle );
  715.             break;
  716.         }
  717.         case eSFX_parameq:
  718.         {
  719.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &g_lpFXManager->m_paramsParamEq.fCenter, DSFXPARAMEQ_CENTER_MIN, DSFXPARAMEQ_CENTER_MAX );
  720.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME2, &g_lpFXManager->m_paramsParamEq.fBandwidth, DSFXPARAMEQ_BANDWIDTH_MIN, DSFXPARAMEQ_BANDWIDTH_MAX );
  721.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME3, &g_lpFXManager->m_paramsParamEq.fGain, DSFXPARAMEQ_GAIN_MIN, DSFXPARAMEQ_GAIN_MAX );
  722.             if( g_lpFXManager->m_lpParamEq )
  723.                 g_lpFXManager->m_lpParamEq->SetAllParameters( &g_lpFXManager->m_paramsParamEq );
  724.             break;
  725.         }
  726.         case eSFX_reverb:
  727.         {
  728.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME1, &g_lpFXManager->m_paramsReverb.fInGain, DSFX_WAVESREVERB_INGAIN_MIN, DSFX_WAVESREVERB_INGAIN_MAX );
  729.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME2, &g_lpFXManager->m_paramsReverb.fReverbMix, DSFX_WAVESREVERB_REVERBMIX_MIN, DSFX_WAVESREVERB_REVERBMIX_MAX );
  730.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME3, &g_lpFXManager->m_paramsReverb.fReverbTime, DSFX_WAVESREVERB_REVERBTIME_MIN, DSFX_WAVESREVERB_REVERBTIME_MAX );
  731.             SaveSingleParameter( hwndDlg, IDC_PARAM_NAME4, &g_lpFXManager->m_paramsReverb.fHighFreqRTRatio, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX, 2 );
  732.             if( g_lpFXManager->m_lpReverb )
  733.                 g_lpFXManager->m_lpReverb->SetAllParameters( &g_lpFXManager->m_paramsReverb );
  734.             break;
  735.         }
  736.     }
  737. }
  738. HRESULT ValidateWaveFile( HWND hDlg, TCHAR* strFileName )
  739. {
  740.     HRESULT hr;
  741.     CWaveFile waveFile;
  742.     if( -1 == GetFileAttributes(strFileName) )
  743.         return E_FAIL;
  744.     
  745.     HANDLE hFile = CreateFile( strFileName, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
  746.     if( hFile != NULL )
  747.     {
  748.         
  749.         
  750.         
  751.         DWORD dwFileSizeHigh = 0;
  752.         DWORD dwFileSize = GetFileSize( hFile, &dwFileSizeHigh );
  753.         CloseHandle( hFile );
  754.         if( dwFileSizeHigh != 0 || dwFileSize > 1000000 )
  755.         {
  756.             SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("File too large.  You should stream large files.") );
  757.             return E_FAIL;
  758.         }
  759.     }
  760.     
  761.     if( FAILED( hr = waveFile.Open( strFileName, NULL, WAVEFILE_READ ) ) )
  762.     {
  763.         waveFile.Close();
  764.         SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Bad wave file.") );
  765.         return DXTRACE_ERR_MSGBOX( TEXT("Open"), hr );
  766.     }
  767.     else 
  768.     {
  769.         WAVEFORMATEX* pwfx = waveFile.GetFormat();
  770.         if( pwfx->wFormatTag != WAVE_FORMAT_PCM && pwfx->wFormatTag != WAVE_FORMAT_IEEE_FLOAT )
  771.         {
  772.             
  773.             SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("Wave file must be PCM or IEEE FLOAT for effects control.") );
  774.             SetDlgItemText( hDlg, IDC_TEXT_FILENAME, TEXT("") );
  775.             return E_FAIL;
  776.         }
  777.         
  778.         waveFile.Close();
  779.         
  780.         SetDlgItemText( hDlg, IDC_TEXT_FILENAME, strFileName );
  781.         SetDlgItemText( hDlg, IDC_TEXT_STATUS, TEXT("File loaded.") );
  782.         strcpy( g_tszFilename, strFileName );
  783.         return S_OK;
  784.     }
  785. }
  786. CSoundFXManager::CSoundFXManager( )
  787. {
  788.     m_lpChorus = NULL;
  789.     m_lpCompressor = NULL;
  790.     m_lpDistortion = NULL;
  791.     m_lpEcho = NULL;
  792.     m_lpFlanger = NULL;
  793.     m_lpGargle = NULL;
  794.     m_lpParamEq = NULL;
  795.     m_lpReverb = NULL;
  796.     ZeroMemory( &m_paramsChorus, sizeof( DSFXChorus ) );
  797.     ZeroMemory( &m_paramsCompressor, sizeof( DSFXCompressor ) );
  798.     ZeroMemory( &m_paramsDistortion, sizeof( DSFXDistortion ) );
  799.     ZeroMemory( &m_paramsFlanger, sizeof( DSFXFlanger ) );
  800.     ZeroMemory( &m_paramsEcho, sizeof( DSFXEcho ) );
  801.     ZeroMemory( &m_paramsGargle, sizeof( DSFXGargle ) );
  802.     ZeroMemory( &m_paramsParamEq, sizeof( DSFXParamEq ) );
  803.     ZeroMemory( &m_paramsReverb, sizeof( DSFXWavesReverb ) );
  804.     m_dwNumFX = 0;
  805.     ZeroMemory( m_rgFxDesc, sizeof( DSEFFECTDESC ) * eNUM_SFX );
  806.     ZeroMemory( m_rgRefGuids, sizeof( GUID * ) * eNUM_SFX );
  807.     ZeroMemory( m_rgPtrs, sizeof(LPVOID*) * eNUM_SFX );
  808.     ZeroMemory( m_rgLoaded, sizeof( BOOL ) * eNUM_SFX );
  809.     m_lpDSB8 = NULL;
  810. }
  811. CSoundFXManager::~CSoundFXManager( )
  812. {
  813.     
  814.     DisableAllFX( );
  815.     
  816.     SAFE_RELEASE( m_lpDSB8 );
  817. }
  818. HRESULT CSoundFXManager::Initialize( LPDIRECTSOUNDBUFFER lpDSB, BOOL bLoadDefaultParamValues )
  819. {
  820.     HRESULT hr;
  821.     if( m_lpDSB8 )
  822.     {
  823.         
  824.         DisableAllFX( );
  825.         SAFE_RELEASE( m_lpDSB8 );
  826.     }
  827.     if( NULL == lpDSB )
  828.         return S_OK;
  829.     
  830.     if( FAILED( hr = lpDSB->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &m_lpDSB8 ) ) )
  831.         return hr;
  832.     if( bLoadDefaultParamValues )
  833.         LoadDefaultParamValues( );
  834.     return S_OK;
  835. }
  836. HRESULT CSoundFXManager::UnInitialize( )
  837. {
  838.     Initialize( NULL, FALSE );
  839.     return S_OK;
  840. }
  841. HRESULT CSoundFXManager::LoadDefaultParamValues( )
  842. {
  843.     DWORD i;
  844.     if( NULL == m_lpDSB8 )
  845.         return E_FAIL;
  846.     for( i = eSFX_chorus; i < eNUM_SFX; i++ )
  847.         SetFXEnable( i );
  848.     ActivateFX( );
  849.     if( m_lpChorus )
  850.         m_lpChorus->GetAllParameters( &m_paramsChorus );
  851.     if( m_lpCompressor )
  852.         m_lpCompressor->GetAllParameters( &m_paramsCompressor );
  853.     if( m_lpDistortion )
  854.         m_lpDistortion->GetAllParameters( &m_paramsDistortion );
  855.     if( m_lpEcho )
  856.         m_lpEcho->GetAllParameters( &m_paramsEcho );
  857.     if( m_lpFlanger )
  858.         m_lpFlanger->GetAllParameters( &m_paramsFlanger );
  859.     if( m_lpGargle )
  860.         m_lpGargle->GetAllParameters( &m_paramsGargle );
  861.     if( m_lpParamEq )
  862.         m_lpParamEq->GetAllParameters( &m_paramsParamEq );
  863.     if( m_lpReverb )
  864.         m_lpReverb->GetAllParameters( &m_paramsReverb );
  865.     DisableAllFX( );
  866.     return S_OK;
  867. }
  868. HRESULT CSoundFXManager::LoadCurrentFXParameters( )
  869. {
  870.     if( m_lpChorus )
  871.         m_lpChorus->SetAllParameters( &m_paramsChorus );
  872.     if( m_lpCompressor )
  873.         m_lpCompressor->SetAllParameters( &m_paramsCompressor );
  874.     if( m_lpDistortion )
  875.         m_lpDistortion->SetAllParameters( &m_paramsDistortion );
  876.     if( m_lpEcho )
  877.         m_lpEcho->SetAllParameters( &m_paramsEcho );
  878.     if( m_lpFlanger )
  879.         m_lpFlanger->SetAllParameters( &m_paramsFlanger );
  880.     if( m_lpGargle )
  881.         m_lpGargle->SetAllParameters( &m_paramsGargle );
  882.     if( m_lpParamEq )
  883.         m_lpParamEq->SetAllParameters( &m_paramsParamEq );
  884.     if( m_lpReverb )
  885.         m_lpReverb->SetAllParameters( &m_paramsReverb );
  886.     return S_OK;
  887. }
  888. HRESULT CSoundFXManager::
  889. SetFXEnable( DWORD esfxType )
  890. {
  891.     HRESULT hr;
  892.     if( esfxType >= eNUM_SFX )
  893.         return E_FAIL;
  894.     if( m_rgLoaded[esfxType] )
  895.         return S_FALSE;
  896.     else
  897.         m_rgLoaded[esfxType] = TRUE;
  898.     switch ( esfxType )
  899.     {
  900.     case eSFX_chorus:
  901.         hr = EnableGenericFX( GUID_DSFX_STANDARD_CHORUS,     IID_IDirectSoundFXChorus8,
  902.                               (LPVOID*) &m_lpChorus );
  903.         break;
  904.     case eSFX_compressor:
  905.         hr = EnableGenericFX( GUID_DSFX_STANDARD_COMPRESSOR, IID_IDirectSoundFXCompressor8,
  906.                               (LPVOID*) &m_lpCompressor );
  907.         break;
  908.     case eSFX_distortion:
  909.         hr = EnableGenericFX( GUID_DSFX_STANDARD_DISTORTION, IID_IDirectSoundFXDistortion8,
  910.                               (LPVOID*) &m_lpDistortion );
  911.         break;
  912.     case eSFX_echo:
  913.         hr = EnableGenericFX( GUID_DSFX_STANDARD_ECHO,       IID_IDirectSoundFXEcho8,
  914.                               (LPVOID*) &m_lpEcho );
  915.         break;
  916.     case eSFX_flanger:
  917.         hr = EnableGenericFX( GUID_DSFX_STANDARD_FLANGER,    IID_IDirectSoundFXFlanger8,
  918.                               (LPVOID*) &m_lpFlanger );
  919.         break;
  920.     case eSFX_gargle:
  921.         hr = EnableGenericFX( GUID_DSFX_STANDARD_GARGLE,     IID_IDirectSoundFXGargle8,
  922.                               (LPVOID*) &m_lpGargle );
  923.         break;
  924.     case eSFX_parameq:
  925.         hr = EnableGenericFX( GUID_DSFX_STANDARD_PARAMEQ,    IID_IDirectSoundFXParamEq8,
  926.                               (LPVOID*) &m_lpParamEq );
  927.         break;
  928.     case eSFX_reverb:
  929.         hr = EnableGenericFX( GUID_DSFX_WAVES_REVERB,        IID_IDirectSoundFXWavesReverb8,
  930.                               (LPVOID*) &m_lpReverb );
  931.         break;
  932.     default:
  933.         hr = E_FAIL;
  934.         break;
  935.     }
  936.     return hr;
  937. }
  938. HRESULT CSoundFXManager::DisableAllFX( )
  939. {
  940.     
  941.     SAFE_RELEASE( m_lpChorus );
  942.     SAFE_RELEASE( m_lpCompressor );
  943.     SAFE_RELEASE( m_lpDistortion );
  944.     SAFE_RELEASE( m_lpEcho );
  945.     SAFE_RELEASE( m_lpFlanger );
  946.     SAFE_RELEASE( m_lpGargle );
  947.     SAFE_RELEASE( m_lpParamEq );
  948.     SAFE_RELEASE( m_lpReverb );
  949.     m_dwNumFX = 0;
  950.     ZeroMemory( m_rgFxDesc, sizeof( DSEFFECTDESC ) * eNUM_SFX );
  951.     ZeroMemory( m_rgRefGuids, sizeof( GUID * ) * eNUM_SFX );
  952.     ZeroMemory( m_rgPtrs, sizeof(LPVOID*) * eNUM_SFX );
  953.     ZeroMemory( m_rgLoaded, sizeof( BOOL ) * eNUM_SFX );
  954.     if( NULL == m_lpDSB8 )
  955.         return E_FAIL;
  956.     
  957.     if( m_lpDSB8 )
  958.         m_lpDSB8->Stop();
  959.     
  960.     m_lpDSB8->SetFX( 0, NULL, NULL );
  961.     return S_OK;
  962. }
  963. HRESULT CSoundFXManager::ActivateFX( )
  964. {
  965.     DWORD dwResults[eNUM_SFX];
  966.     HRESULT hr;
  967.     DWORD i;
  968.     if( NULL == m_lpDSB8 )
  969.         return E_FAIL;
  970.     if( m_dwNumFX == 0 )
  971.         return S_FALSE;
  972.     if( FAILED( hr = m_lpDSB8->SetFX( m_dwNumFX, m_rgFxDesc, dwResults ) ) )
  973.         return hr;
  974.     
  975.     for( i = 0; i < m_dwNumFX; i++ )
  976.         if( FAILED( hr = m_lpDSB8->GetObjectInPath( m_rgFxDesc[i].guidDSFXClass, 0, *m_rgRefGuids[i], m_rgPtrs[i] ) ) )
  977.             return DXTRACE_ERR_MSGBOX( TEXT("GetObjectInPath"), hr );
  978.     return S_OK;
  979. }
  980. HRESULT CSoundFXManager::EnableGenericFX( GUID guidSFXClass, REFGUID rguidInterface, LPVOID * ppObj )
  981. {
  982.     
  983.     if( *ppObj )
  984.         return S_FALSE;
  985.     if( m_dwNumFX >= eNUM_SFX )
  986.         return E_FAIL;
  987.     
  988.     ZeroMemory( &m_rgFxDesc[m_dwNumFX], sizeof(DSEFFECTDESC) );
  989.     m_rgFxDesc[m_dwNumFX].dwSize         = sizeof(DSEFFECTDESC);
  990.     m_rgFxDesc[m_dwNumFX].dwFlags        = 0;
  991.     CopyMemory( &m_rgFxDesc[m_dwNumFX].guidDSFXClass, &guidSFXClass, sizeof(GUID) );
  992.     m_rgRefGuids[m_dwNumFX] = &rguidInterface;
  993.     m_rgPtrs[m_dwNumFX] = ppObj;
  994.     m_dwNumFX++;
  995.     return S_OK;
  996. }