|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// voice_tweakDlg.cpp : implementation file
//
#include "stdafx.h"
#include "voice_tweak.h"
#include "voice_tweakDlg.h"
#include "voice_gain.h"
#include "dvoice.h"
void TermDPlayVoice( HINSTANCE &hInst, IDirectPlayVoiceTest* &pVoice ) { if( pVoice ) { pVoice->Release(); pVoice = NULL; }
if( hInst ) { FreeLibrary( hInst ); hInst = NULL; } }
bool InitDPlayVoice( HINSTANCE &hInst, IDirectPlayVoiceTest* &pVoice ) { typedef HRESULT (WINAPI *DirectPlayVoiceCreateFn)( GUID* pcIID, void** ppvInterface, IUnknown* pUnknown );
hInst = NULL; pVoice = NULL;
hInst = LoadLibrary( "dpvoice.dll" ); if(hInst) { DirectPlayVoiceCreateFn fn = (DirectPlayVoiceCreateFn)GetProcAddress(hInst, "DirectPlayVoiceCreate"); if(fn) { HRESULT hr = fn((GUID*)&IID_IDirectPlayVoiceTest, (void**)&pVoice, NULL); if( SUCCEEDED( hr ) ) return true; } }
TermDPlayVoice( hInst, pVoice ); return false; }
bool IsDPlayVoiceAvailable() { HINSTANCE hInst; IDirectPlayVoiceTest *pVoice;
bool bRet = InitDPlayVoice( hInst, pVoice ); TermDPlayVoice( hInst, pVoice );
return bRet; }
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
#define VOLUMESLIDER_RANGE 1000
CVoiceTweakApp* TweakApp() {return (CVoiceTweakApp*)AfxGetApp();}
extern "C" { void Con_DPrintf (char *fmt, ...); void Con_Printf (char *fmt, ...); }
void PrintToTraceWindow(const char *fmt, va_list marker) { char msg[2048]; _vsnprintf(msg, sizeof(msg), fmt, marker); OutputDebugString(msg); }
void Con_DPrintf (char *fmt, ...) { va_list marker; va_start(marker, fmt); PrintToTraceWindow(fmt, marker); va_end(marker); }
void Con_Printf (char *fmt, ...) { va_list marker; va_start(marker, fmt); PrintToTraceWindow(fmt, marker); va_end(marker); }
/////////////////////////////////////////////////////////////////////////////
// CVoiceTweakDlg dialog
CVoiceTweakDlg::CVoiceTweakDlg(CWnd* pParent /*=NULL*/) : CDialog(CVoiceTweakDlg::IDD, pParent) { //{{AFX_DATA_INIT(CVoiceTweakDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); }
CVoiceTweakDlg::~CVoiceTweakDlg() { Term(); }
void CVoiceTweakDlg::Term() { m_WinIdle.EndIdle(); }
void CVoiceTweakDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CVoiceTweakDlg)
DDX_Control(pDX, IDC_HARDWAREGAIN, m_HardwareGain); DDX_Control(pDX, IDC_VOICEVOLUME, m_VoiceVolume); DDX_Control(pDX, IDC_VOLUMESLIDER, m_VolumeSlider); DDX_Control(pDX, IDC_INSTRUCTIONTEXT, m_InstructionText); //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CVoiceTweakDlg, CDialog) //{{AFX_MSG_MAP(CVoiceTweakDlg)
ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(WM_TWEAKIDLE, OnIdle) ON_WM_DESTROY() ON_BN_CLICKED(IDC_HARDWAREGAIN, OnHardwareGain) ON_BN_CLICKED(IDFURTHERHELP, OnFurtherhelp) ON_BN_CLICKED(IDSYSTEMSETUP, OnSystemSetup) //}}AFX_MSG_MAP
END_MESSAGE_MAP()
IMixerControls* GetAppMixerControls() { return ((CVoiceTweakApp*)AfxGetApp())->m_pMixerControls; }
void CVoiceTweakDlg::SetString(int childControl, int stringID) { if(CWnd *pWnd = GetDlgItem(childControl)) { CString str; str.LoadString(stringID); pWnd->SetWindowText(str); } }
/////////////////////////////////////////////////////////////////////////////
// CVoiceTweakDlg message handlers
BOOL CVoiceTweakDlg::OnInitDialog() { CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
CString str; str.LoadString( MapLanguageStringID(IDS_HELPTEXT) ); m_InstructionText.SetWindowText(str);
// Save off their old settings so we can restore if they hit cancel.
GetAppMixerControls()->GetValue_Float(IMixerControls::Control::MicVolume, m_OldVolume);
float bBoostOn; if(GetAppMixerControls()->GetValue_Float(IMixerControls::Control::MicBoost, bBoostOn)) { m_HardwareGain.SetCheck((int)bBoostOn); } else { m_HardwareGain.ShowWindow(SW_HIDE); }
// Initialize the volume control.
m_VolumeSlider.SetRange(0, 1000); m_VolumeSlider.SetPos((int)(VOLUMESLIDER_RANGE - m_OldVolume * VOLUMESLIDER_RANGE));
m_VoiceVolume.SetRange32(0, (1 << (BYTES_PER_SAMPLE*8-1)) - 1);
// Get idle messages...
m_WinIdle.StartIdle(GetSafeHwnd(), WM_TWEAKIDLE, 0,0, 10); m_WinIdle.NextIdle();
// Set all the dialog item strings for localization.
SetString(IDOK, MapLanguageStringID(IDS_OKAY)); SetString(IDCANCEL, MapLanguageStringID(IDS_CANCEL)); SetString(IDC_VOICEINPUTFRAME, MapLanguageStringID(IDS_VOICEINPUT)); SetString(IDC_VOLUMELABEL, MapLanguageStringID(IDS_VOLUME)); SetString(IDC_HARDWAREGAIN, MapLanguageStringID(IDS_ENABLEGAIN)); SetString(IDSYSTEMSETUP, MapLanguageStringID(IDS_SYSTEMSETUP)); SetString(IDFURTHERHELP, MapLanguageStringID(IDS_HELP)); CString titleStr; titleStr.LoadString( MapLanguageStringID(IDS_WINDOWTITLE) ); SetWindowText(titleStr);
if( !IsDPlayVoiceAvailable() ) { CWnd *pWnd = GetDlgItem( IDSYSTEMSETUP ); if( pWnd ) pWnd->EnableWindow( false ); } return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CVoiceTweakDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } }
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CVoiceTweakDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; }
BOOL CVoiceTweakDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { NMHDR *pHdr = (NMHDR*)lParam; if(pHdr->hwndFrom == m_VolumeSlider.m_hWnd) { GetAppMixerControls()->SetValue_Float(IMixerControls::Control::MicVolume, (VOLUMESLIDER_RANGE - m_VolumeSlider.GetPos()) / (float)VOLUMESLIDER_RANGE); }
return CDialog::OnNotify(wParam, lParam, pResult); }
LONG CVoiceTweakDlg::OnIdle(UINT a, LONG b) { static DWORD startTime = GetTickCount();
if( TweakApp()->m_pVoiceRecord ) { short samples[22 * 1024]; // If the output has too many buffered samples, skip some data.
TweakApp()->m_pWaveOut->Idle(); int nBufferedSamples = TweakApp()->m_pWaveOut->GetNumBufferedSamples(); float nSeconds = nBufferedSamples / (float)VOICE_TWEAK_SAMPLE_RATE; int nMinSamples = VOICE_TWEAK_SAMPLE_RATE / 5; if( nBufferedSamples < nMinSamples ) { // We want at least a certain amount of buffered data.
int nSamplesToAdd = nMinSamples - nBufferedSamples; memset( samples, 0, nSamplesToAdd*2 ); TweakApp()->m_pWaveOut->PutSamples( samples, nSamplesToAdd ); } else { // Get the samples.
int nSamples = TweakApp()->m_pVoiceRecord->GetRecordedData(samples, sizeof(samples)/BYTES_PER_SAMPLE); if( nSeconds < 0.5f ) { // Find the highest value.
int highValue = -100000; for(int i=0; i < nSamples; i++) highValue = max(abs(samples[i]), highValue);
// Set our status bar accordingly.
highValue = (highValue >> 9) << 9; // Get rid of flicker.
m_VoiceVolume.SetPos(highValue);
// Give the samples to the wave output...
if(TweakApp()->m_pWaveOut) { // Ignore the first second or so.. it's usually garbage.
DWORD curTime = GetTickCount(); static DWORD silentTime = 500; static DWORD fadeInTime = 1000; if( curTime - startTime < silentTime ) { memset( samples, 0, nSamples*2 ); } else if( (curTime-silentTime) - startTime < fadeInTime ) { float flFade = ((curTime-silentTime) - startTime) / (float)fadeInTime; flFade = flFade*flFade; for( int i=0; i < nSamples; i++ ) samples[i] = (short)( samples[i] * flFade ); } TweakApp()->m_pWaveOut->PutSamples(samples, nSamples); } } } }
// Tell the idle thread we're ready for another idle message.
m_WinIdle.NextIdle(); return 0; }
void CVoiceTweakDlg::OnDestroy() { Term();
CDialog::OnDestroy(); }
void CVoiceTweakDlg::OnHardwareGain() { if(m_HardwareGain.GetCheck()) GetAppMixerControls()->SetValue_Float(IMixerControls::Control::MicBoost, true); else GetAppMixerControls()->SetValue_Float(IMixerControls::Control::MicBoost, false); }
void CVoiceTweakDlg::OnCancel() { // Restore old settings.
GetAppMixerControls()->SetValue_Float(IMixerControls::Control::MicVolume, m_OldVolume); CDialog::OnCancel(); }
void CVoiceTweakDlg::OnFurtherhelp() { }
void CVoiceTweakDlg::OnSystemSetup() { TweakApp()->StopDevices();
bool bSucceeded = false; HINSTANCE hInst; IDirectPlayVoiceTest *pVoice; if( InitDPlayVoice( hInst, pVoice ) ) { pVoice->CheckAudioSetup(NULL, NULL, m_hWnd, DVFLAGS_ALLOWBACK); TermDPlayVoice( hInst, pVoice ); } else { CString str; str.LoadString( MapLanguageStringID(IDS_NODPLAYVOICE) ); MessageBox(str); }
if(!TweakApp()->StartDevices()) AfxPostQuitMessage(0); }
|