2017-03-15 19:43:10 +00:00
|
|
|
// SoundPage.cpp : implementation file
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "source_sounds_builder.h"
|
|
|
|
#include "source_sounds_builderDlg.h"
|
|
|
|
#include "SoundPage.h"
|
|
|
|
|
|
|
|
#include "../src/sound/driver/buffer.h"
|
|
|
|
#include "../src/sound/audio_mixer_user.h"
|
|
|
|
|
|
|
|
#include "nel/sound/u_listener.h"
|
|
|
|
|
|
|
|
#include <nel/misc/common.h>
|
|
|
|
#include <nel/misc/vector.h>
|
|
|
|
using namespace NLMISC;
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
#undef THIS_FILE
|
|
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#define CONE_X 340
|
|
|
|
#define CONE_Y 280
|
|
|
|
#define CONE_R 30
|
|
|
|
|
|
|
|
|
|
|
|
uint XCenter;
|
|
|
|
uint YCenter;
|
|
|
|
uint Radius;
|
|
|
|
|
|
|
|
|
|
|
|
const char *PriorityStr [NbSoundPriorities] = { "Highest", "High", "Medium", "Low" };
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------
|
|
|
|
// Name: ConvertLinearSliderPosToLogScale()
|
|
|
|
// Desc: Converts a linear slider position to a quasi logrithmic scale
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float ConvertLinearSliderPosToLogScale( LONG lSliderPos )
|
|
|
|
{
|
|
|
|
if( lSliderPos > 0 && lSliderPos <= 10 )
|
|
|
|
{
|
|
|
|
return lSliderPos*0.01f;
|
|
|
|
}
|
|
|
|
else if( lSliderPos > 10 && lSliderPos <= 20 )
|
|
|
|
{
|
|
|
|
return (lSliderPos-10)*0.1f;
|
|
|
|
}
|
|
|
|
else if( lSliderPos > 20 && lSliderPos <= 30 )
|
|
|
|
{
|
|
|
|
return (lSliderPos-20)*1.0f;
|
|
|
|
}
|
|
|
|
else if( lSliderPos > 30 && lSliderPos <= 40 )
|
|
|
|
{
|
|
|
|
return (lSliderPos-30)*10.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Name: ConvertLinearSliderPosToLogScale()
|
|
|
|
// Desc: Converts a quasi logrithmic scale to a slider position
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
LONG ConvertLogScaleToLinearSliderPosTo( FLOAT fValue )
|
|
|
|
{
|
|
|
|
if( fValue > 0.0f && fValue <= 0.1f )
|
|
|
|
{
|
|
|
|
return (LONG)(fValue/0.01f);
|
|
|
|
}
|
|
|
|
else if( fValue > 0.1f && fValue <= 1.0f )
|
|
|
|
{
|
|
|
|
return (LONG)(fValue/0.1f) + 10;
|
|
|
|
}
|
|
|
|
else if( fValue > 1.0f && fValue <= 10.0f )
|
|
|
|
{
|
|
|
|
return (LONG)(fValue/1.0f) + 20;
|
|
|
|
}
|
|
|
|
else if( fValue > 10.0f && fValue <= 100.0f )
|
|
|
|
{
|
|
|
|
return (LONG)(fValue/10.0f) + 30;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CSoundPage dialog
|
|
|
|
|
|
|
|
|
|
|
|
CSoundPage::CSoundPage(CWnd* pParent /*=NULL*/)
|
|
|
|
: CDialog(CSoundPage::IDD, pParent)
|
|
|
|
{
|
|
|
|
//{{AFX_DATA_INIT(CSoundPage)
|
|
|
|
m_Filename = _T("");
|
|
|
|
m_Gain = 1.0f;
|
|
|
|
m_Pos3D = FALSE;
|
|
|
|
m_MinDist = 1.0f;
|
|
|
|
m_MaxDist = 1000000.0f;
|
|
|
|
m_InnerAngleDeg = 360;
|
|
|
|
m_OuterAngleDeg = 360;
|
|
|
|
m_OuterGain = 1.0f;
|
|
|
|
m_Looped = FALSE;
|
|
|
|
m_Stereo = _T("");
|
|
|
|
m_Pitch = 1.0f;
|
|
|
|
m_Looping = false;
|
|
|
|
m_SoundName = _T("");
|
|
|
|
//}}AFX_DATA_INIT
|
|
|
|
|
|
|
|
_CurrentSound = NULL;
|
|
|
|
_Tree = NULL;
|
|
|
|
_Source = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
BOOL CSoundPage::OnInitDialog()
|
|
|
|
{
|
|
|
|
CDialog::OnInitDialog();
|
|
|
|
|
|
|
|
// Load driver
|
|
|
|
CWaitCursor waitcursor;
|
|
|
|
_AudioMixer = UAudioMixer::createAudioMixer();
|
|
|
|
try
|
|
|
|
{
|
|
|
|
_AudioMixer->init();
|
|
|
|
//_AudioMixer->getListener()->setPos( CVector(0.0f,0.0001f,0.0f) );
|
|
|
|
}
|
|
|
|
catch( Exception& e )
|
|
|
|
{
|
|
|
|
CString s;
|
|
|
|
s.Format( "No sound driver: %s\n\nSound playback will be unavailable" , e.what() );
|
|
|
|
AfxMessageBox( s );
|
|
|
|
_AudioMixer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill priorities
|
|
|
|
uint i;
|
|
|
|
for ( i=0; i!=NbSoundPriorities; ++i )
|
|
|
|
{
|
|
|
|
m_Priority.AddString( PriorityStr[i] );
|
|
|
|
}
|
|
|
|
|
|
|
|
// We want to load nss files even if the corresponding waves are missing
|
|
|
|
CSound::allowMissingWave( true );
|
|
|
|
|
|
|
|
// Cone drawing: make it work with normal and big fonts (depending on system settings)
|
|
|
|
CRect parentrect, sliderrect;
|
|
|
|
this->GetWindowRect( &parentrect );
|
|
|
|
GetDlgItem( IDC_SliderOuterAngle )->GetWindowRect( &sliderrect );
|
|
|
|
XCenter = sliderrect.right - parentrect.left + 15 + CONE_R;
|
|
|
|
YCenter = sliderrect.top - parentrect.top + 10;
|
|
|
|
Radius = CONE_R;
|
|
|
|
|
|
|
|
waitcursor.Restore();
|
|
|
|
|
|
|
|
_NameFont = new CFont();
|
|
|
|
LOGFONT logfont;
|
|
|
|
GetFont()->GetLogFont( &logfont );
|
|
|
|
logfont.lfWeight = FW_BOLD;
|
|
|
|
_NameFont->CreateFontIndirect( &logfont );
|
|
|
|
|
|
|
|
GetDlgItem( IDC_SoundName )->SetFont( _NameFont );
|
|
|
|
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderGain ))->SetRange( 0, 40 );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderPitch ))->SetRange( 0, 40 );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderMinDist ))->SetRange( 0, 1000 );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderMaxDist ))->SetRange( 0, 1000 );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderInnerAngle ))->SetRange( 0, 360 );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderOuterAngle ))->SetRange( 0, 360 );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderOuterGain ))->SetRange( 0, 40 );
|
|
|
|
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSoundPage::DoDataExchange(CDataExchange* pDX)
|
|
|
|
{
|
|
|
|
CDialog::DoDataExchange(pDX);
|
|
|
|
//{{AFX_DATA_MAP(CSoundPage)
|
|
|
|
DDX_Control(pDX, IDC_CbPriority, m_Priority);
|
|
|
|
DDX_Text(pDX, IDC_EditFilename, m_Filename);
|
|
|
|
DDX_Text(pDX, IDC_EditGain, m_Gain);
|
|
|
|
DDV_MinMaxFloat(pDX, m_Gain, 0.f, 1.f);
|
|
|
|
DDX_Check(pDX, IDC_Pos3D, m_Pos3D);
|
|
|
|
DDX_Text(pDX, IDC_EditMinDist, m_MinDist);
|
|
|
|
DDV_MinMaxFloat(pDX, m_MinDist, 0.f, 1.e+006f);
|
|
|
|
DDX_Text(pDX, IDC_EditMaxDist, m_MaxDist);
|
|
|
|
DDV_MinMaxFloat(pDX, m_MaxDist, 0.f, 1.e+006f);
|
|
|
|
DDX_Text(pDX, IDC_EditInnerAngle, m_InnerAngleDeg);
|
|
|
|
DDV_MinMaxUInt(pDX, m_InnerAngleDeg, 0, 360);
|
|
|
|
DDX_Text(pDX, IDC_EditOuterAngle, m_OuterAngleDeg);
|
|
|
|
DDV_MinMaxUInt(pDX, m_OuterAngleDeg, 0, 360);
|
|
|
|
DDX_Text(pDX, IDC_EditOuterGain, m_OuterGain);
|
|
|
|
DDV_MinMaxFloat(pDX, m_OuterGain, 0.f, 1.f);
|
|
|
|
DDX_Check(pDX, IDC_Looped, m_Looped);
|
|
|
|
DDX_Text(pDX, IDC_Stereo, m_Stereo);
|
|
|
|
DDX_Text(pDX, IDC_EditPitch, m_Pitch);
|
|
|
|
DDV_MinMaxFloat(pDX, m_Pitch, 1.e-011f, 1.f);
|
|
|
|
DDX_Check(pDX, IDC_Looping, m_Looping);
|
|
|
|
DDX_Text(pDX, IDC_SoundName, m_SoundName);
|
|
|
|
//}}AFX_DATA_MAP
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CSoundPage, CDialog)
|
|
|
|
//{{AFX_MSG_MAP(CSoundPage)
|
|
|
|
ON_BN_CLICKED(IDC_Pos3D, OnPos3D)
|
|
|
|
ON_BN_CLICKED(IDC_ChooseFile, OnChooseFile)
|
|
|
|
ON_BN_CLICKED(IDC_Remove, OnRemove)
|
|
|
|
ON_BN_CLICKED(IDC_PlaySound, OnPlaySound)
|
|
|
|
ON_WM_CLOSE()
|
|
|
|
ON_BN_CLICKED(IDC_Looped, OnLooped)
|
|
|
|
ON_EN_CHANGE(IDC_EditInnerAngle, OnChangeEditInnerAngle)
|
|
|
|
ON_EN_CHANGE(IDC_EditOuterAngle, OnChangeEditOuterAngle)
|
|
|
|
ON_WM_PAINT()
|
|
|
|
ON_EN_CHANGE(IDC_EditOuterGain, OnChangeEditOuterGain)
|
|
|
|
ON_WM_HSCROLL()
|
|
|
|
ON_EN_CHANGE(IDC_EditMinDist, OnChangeEditMinDist)
|
|
|
|
ON_EN_CHANGE(IDC_EditMaxDist, OnChangeEditMaxDist)
|
|
|
|
ON_BN_CLICKED(IDC_ButtonHelp, OnButtonHelp)
|
|
|
|
ON_EN_CHANGE(IDC_EditGain, OnChangeEditGain)
|
|
|
|
ON_BN_CLICKED(IDC_ButtonTestOuterGain, OnButtonTestOuterGain)
|
|
|
|
ON_EN_CHANGE(IDC_EditPitch, OnChangeEditPitch)
|
|
|
|
ON_BN_CLICKED(IDC_Cancel, OnCancel)
|
|
|
|
ON_BN_CLICKED(IDC_Home, OnHome)
|
|
|
|
//}}AFX_MSG_MAP
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
const char *StereoToCStr( CSound* snd, bool *st )
|
|
|
|
{
|
|
|
|
static const char empty [] = "";
|
|
|
|
static const char mono [] = "Mono";
|
|
|
|
static const char stereo [] = "Stereo";
|
|
|
|
if ( snd->getBuffer() == NULL )
|
|
|
|
{
|
|
|
|
*st = false;
|
|
|
|
return empty;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( snd->getBuffer()->isStereo() )
|
|
|
|
{
|
|
|
|
*st = true;
|
|
|
|
return stereo;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*st = false;
|
|
|
|
return mono;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::UpdateStereo()
|
|
|
|
{
|
|
|
|
bool stereo;
|
|
|
|
m_Stereo = StereoToCStr( _CurrentSound, &stereo );
|
|
|
|
if ( stereo )
|
|
|
|
{
|
|
|
|
m_Pos3D = false;
|
|
|
|
}
|
|
|
|
GetDlgItem( IDC_Pos3D )->EnableWindow( ! stereo );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::getPropertiesFromSound()
|
|
|
|
{
|
|
|
|
m_SoundName = _CurrentSound->getName().c_str();
|
|
|
|
m_Filename = _CurrentSound->getFilename().c_str();
|
|
|
|
m_Gain = _CurrentSound->getGain();
|
|
|
|
m_Pitch = _CurrentSound->getPitch();
|
|
|
|
m_Priority.SetCurSel( _CurrentSound->getPriority() );
|
|
|
|
m_Looping = _CurrentSound->getLooping();
|
|
|
|
m_Pos3D = _CurrentSound->isDetailed();
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderGain ))->SetPos( ConvertLogScaleToLinearSliderPosTo( m_Gain*100.0f ) );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderPitch ))->SetPos( ConvertLogScaleToLinearSliderPosTo( m_Pitch*100.0f ) );
|
|
|
|
UpdateStereo();
|
|
|
|
|
|
|
|
if ( m_Pos3D )
|
|
|
|
{
|
|
|
|
m_MinDist = _CurrentSound->getMinDistance();
|
|
|
|
m_MaxDist = _CurrentSound->getMaxDistance();
|
|
|
|
m_InnerAngleDeg = (uint)radToDeg( _CurrentSound->getConeInnerAngle() );
|
|
|
|
m_OuterAngleDeg = (uint)radToDeg( _CurrentSound->getConeOuterAngle() );
|
|
|
|
m_OuterGain = _CurrentSound->getConeOuterGain();
|
|
|
|
}
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderMinDist ))->SetPos( (int)m_MinDist );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderMaxDist ))->SetPos( (int)m_MaxDist );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderInnerAngle ))->SetPos( m_InnerAngleDeg );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderOuterAngle ))->SetPos( m_OuterAngleDeg );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderOuterGain ))->SetPos( ConvertLogScaleToLinearSliderPosTo( m_OuterGain*100.0f ) );
|
|
|
|
UpdateData( false );
|
|
|
|
|
|
|
|
Invalidate();
|
|
|
|
OnPos3D(); // enable/disable 3d properties
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::UpdateCurrentSound()
|
|
|
|
{
|
|
|
|
CString name = ((CSource_sounds_builderDlg*)GetOwner())->SoundName( _HItem );
|
|
|
|
if ( ! m_Pos3D )
|
|
|
|
{
|
|
|
|
_CurrentSound->setProperties( string(name), string(m_Filename), m_Gain, m_Pitch, (TSoundPriority)(m_Priority.GetCurSel()), m_Looping!=0, m_Pos3D!=0 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_CurrentSound->setProperties( string(name), string(m_Filename), m_Gain, m_Pitch, (TSoundPriority)(m_Priority.GetCurSel()), m_Looping!=0, m_Pos3D!=0,
|
|
|
|
m_MinDist, m_MaxDist, degToRad((float)m_InnerAngleDeg), degToRad((float)m_OuterAngleDeg), m_OuterGain );
|
|
|
|
}
|
|
|
|
// Argument checking is already done by the dialog wizard
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CSoundPage message handlers
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::setCurrentSound( CSound *sound, HTREEITEM hitem )
|
|
|
|
{
|
|
|
|
_CurrentSound = sound;
|
|
|
|
_HItem = hitem;
|
|
|
|
if ( _Source != NULL )
|
|
|
|
{
|
|
|
|
_Source->stop();
|
|
|
|
}
|
|
|
|
m_Looped = false;
|
|
|
|
UpdateData( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnPos3D()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
GetDlgItem( IDC_Pos3DGroup )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_MinDist )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_MaxDist )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_ConeInnerAngle )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_ConeOuterAngle )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_ConeOuterGain )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_EditMinDist )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_EditMaxDist )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_EditInnerAngle )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_EditOuterAngle )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_EditOuterGain )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_SliderMinDist )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_SliderMaxDist )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_SliderInnerAngle )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_SliderOuterAngle )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_SliderOuterGain )->EnableWindow( m_Pos3D );
|
|
|
|
GetDlgItem( IDC_ButtonTestOuterGain )->EnableWindow( m_Pos3D );
|
|
|
|
|
|
|
|
DrawCones();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::apply()
|
|
|
|
{
|
|
|
|
if ( _CurrentSound )
|
|
|
|
{
|
|
|
|
if ( _Source != NULL )
|
|
|
|
{
|
|
|
|
_Source->stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateData( true );
|
|
|
|
|
|
|
|
UpdateCurrentSound();
|
|
|
|
|
|
|
|
//(static_cast<CSource_sounds_builderDlg*>(GetOwner()))->setModified();
|
|
|
|
|
|
|
|
nlassert( _Tree );
|
|
|
|
|
|
|
|
if ( !m_Filename.empty() )
|
|
|
|
{
|
|
|
|
CString s = ((CSource_sounds_builderDlg*)GetOwner())->SoundName( _HItem ) + " (" + m_Filename + ")";
|
|
|
|
_Tree->SetItemText( _HItem, s );
|
|
|
|
}
|
|
|
|
|
|
|
|
//_Tree->SelectItem( NULL );
|
|
|
|
|
|
|
|
GetOwner()->SetFocus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::rename( CString s )
|
|
|
|
{
|
|
|
|
// Quick way to do it (should be simplified)
|
|
|
|
|
|
|
|
getPropertiesFromSound();
|
|
|
|
nlassert( _Tree );
|
|
|
|
_Tree->SetItemText( _HItem, s );
|
|
|
|
UpdateCurrentSound();
|
|
|
|
|
|
|
|
m_SoundName = s;
|
|
|
|
UpdateData( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reverts the changes
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnCancel()
|
|
|
|
{
|
|
|
|
getPropertiesFromSound();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unselects the current sound
|
|
|
|
*/
|
|
|
|
void CSoundPage::cancel()
|
|
|
|
{
|
|
|
|
if ( _Source != NULL )
|
|
|
|
{
|
|
|
|
_Source->stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
_CurrentSound = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnHome()
|
|
|
|
{
|
|
|
|
nlassert( _Tree );
|
|
|
|
_Tree->SelectItem( _Tree->GetRootItem() );
|
|
|
|
GetOwner()->SetFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChooseFile()
|
|
|
|
{
|
|
|
|
// Prompt filename
|
|
|
|
CFileDialog opendlg( true, "wav", "", OFN_OVERWRITEPROMPT, "PCM Wave files (*.wav)|*.wav||", this );
|
|
|
|
if ( opendlg.DoModal()==IDOK )
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
m_Filename = opendlg.GetFileName();
|
|
|
|
try
|
|
|
|
{
|
|
|
|
loadSound();
|
|
|
|
}
|
|
|
|
catch ( Exception& e )
|
|
|
|
{
|
|
|
|
CString s;
|
|
|
|
s.Format( "%s", e.what() );
|
|
|
|
AfxMessageBox( s );
|
|
|
|
}
|
|
|
|
UpdateData( false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
bool CSoundPage::loadSound()
|
|
|
|
{
|
|
|
|
UpdateCurrentSound();
|
|
|
|
nlassert( _CurrentSound );
|
|
|
|
if ( (m_Filename != "") && (_AudioMixer != NULL) )
|
|
|
|
{
|
|
|
|
_CurrentSound->loadBuffer( string(m_Filename) );
|
|
|
|
UpdateStereo();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnRemove()
|
|
|
|
{
|
|
|
|
removeSound();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::removeSound()
|
|
|
|
{
|
|
|
|
/*if ( AfxMessageBox( "Are you sure to remove the current sound from the list ?", MB_YESNO | MB_ICONQUESTION ) == IDYES )
|
|
|
|
{*/
|
|
|
|
if ( _CurrentSound )
|
|
|
|
{
|
|
|
|
nlassert( _Tree );
|
|
|
|
_Tree->DeleteItem( _HItem );
|
|
|
|
}
|
|
|
|
/*}*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::Play( bool outsidecone )
|
|
|
|
{
|
|
|
|
CWaitCursor waitcursor;
|
|
|
|
|
|
|
|
// Load sound
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if ( loadSound() )
|
|
|
|
{
|
|
|
|
UpdateData( false );
|
|
|
|
|
|
|
|
// Play source
|
|
|
|
if ( _Source == NULL )
|
|
|
|
{
|
|
|
|
_Source = _AudioMixer->createSource( _CurrentSound );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_Source->stop();
|
|
|
|
_Source->setSound( _CurrentSound );
|
|
|
|
}
|
|
|
|
_Source->setLooping( m_Looped!=0 );
|
|
|
|
if ( outsidecone )
|
|
|
|
{
|
|
|
|
// The listener is just behind the source
|
|
|
|
_Source->setPos( CVector(0.0f,0.1f,0.0f) );
|
|
|
|
_Source->setDirection( CVector(0.0f,1.0f,0.0f) ); // directional
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The listener is at the source pos
|
|
|
|
_Source->setPos( CVector(0.0f,0.0f,0.0f) );
|
|
|
|
_Source->setDirection( CVector(0.0f,0.0f,0.0f) ); // non-directional
|
|
|
|
}
|
|
|
|
_Source->play();
|
|
|
|
}
|
|
|
|
|
|
|
|
waitcursor.Restore();
|
|
|
|
}
|
|
|
|
catch ( Exception& e )
|
|
|
|
{
|
|
|
|
waitcursor.Restore();
|
|
|
|
|
|
|
|
CString s;
|
|
|
|
s.Format( "%s", e.what() );
|
|
|
|
AfxMessageBox( s );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnPlaySound()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
m_Looped = false;
|
|
|
|
Play( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnLooped()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
if ( m_Looped )
|
|
|
|
{
|
|
|
|
Play( false );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( _Source != NULL )
|
|
|
|
{
|
|
|
|
_Source->stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnButtonTestOuterGain()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
m_Looped = false;
|
|
|
|
Play( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnClose()
|
|
|
|
{
|
|
|
|
if ( _AudioMixer != NULL )
|
|
|
|
{
|
|
|
|
if ( _Source != NULL )
|
|
|
|
{
|
|
|
|
delete _Source;
|
|
|
|
}
|
|
|
|
delete _AudioMixer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::DrawCones()
|
|
|
|
{
|
|
|
|
if ( m_InnerAngleDeg > m_OuterAngleDeg )
|
|
|
|
{
|
|
|
|
GetDlgItem( IDC_BadCone )->SetWindowText( "Inner > Outer !" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GetDlgItem( IDC_BadCone )->SetWindowText( "" );
|
|
|
|
}
|
|
|
|
|
|
|
|
CRect rect( XCenter-Radius, YCenter-Radius, XCenter+Radius+1, YCenter+Radius+1 );
|
|
|
|
InvalidateRect( &rect, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChangeEditGain()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderGain ))->SetPos( ConvertLogScaleToLinearSliderPosTo( m_Gain*100.0f ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChangeEditPitch()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderPitch ))->SetPos( ConvertLogScaleToLinearSliderPosTo( m_Pitch*100.0f ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChangeEditMinDist()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderMinDist ))->SetPos( (int)m_MinDist );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChangeEditMaxDist()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderMaxDist ))->SetPos( (int)m_MaxDist );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChangeEditInnerAngle()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderInnerAngle ))->SetPos( m_InnerAngleDeg );
|
|
|
|
DrawCones();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChangeEditOuterAngle()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderOuterAngle ))->SetPos( m_OuterAngleDeg );
|
|
|
|
DrawCones();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnChangeEditOuterGain()
|
|
|
|
{
|
|
|
|
UpdateData( true );
|
|
|
|
((CSliderCtrl*)GetDlgItem( IDC_SliderOuterGain ))->SetPos( ConvertLogScaleToLinearSliderPosTo( m_OuterGain*100.0f) );
|
|
|
|
DrawCones();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
|
|
|
|
{
|
|
|
|
CSliderCtrl *slider = (CSliderCtrl*)pScrollBar; // MFC sucks
|
|
|
|
|
|
|
|
nPos = slider->GetPos();
|
|
|
|
{
|
|
|
|
if ( slider == GetDlgItem( IDC_SliderGain ) )
|
|
|
|
{
|
|
|
|
m_Gain = ConvertLinearSliderPosToLogScale( nPos ) / 100.0f;
|
|
|
|
if ( _Source != NULL )
|
|
|
|
{
|
|
|
|
_Source->setGain( m_Gain );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( slider == GetDlgItem( IDC_SliderPitch ) )
|
|
|
|
{
|
|
|
|
m_Pitch = ConvertLinearSliderPosToLogScale( nPos ) / 100.0f;
|
|
|
|
if ( _Source != NULL )
|
|
|
|
{
|
|
|
|
_Source->setPitch( m_Pitch );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( slider == GetDlgItem( IDC_SliderMinDist ) )
|
|
|
|
{
|
|
|
|
m_MinDist = (float)nPos;
|
|
|
|
}
|
|
|
|
else if ( slider == GetDlgItem( IDC_SliderMaxDist ) )
|
|
|
|
{
|
|
|
|
m_MaxDist = (float)nPos;
|
|
|
|
}
|
|
|
|
else if ( slider == GetDlgItem( IDC_SliderInnerAngle ) )
|
|
|
|
{
|
|
|
|
m_InnerAngleDeg = nPos;
|
|
|
|
}
|
|
|
|
else if ( slider == GetDlgItem( IDC_SliderOuterAngle ) )
|
|
|
|
{
|
|
|
|
m_OuterAngleDeg = nPos;
|
|
|
|
}
|
|
|
|
else if ( slider == GetDlgItem( IDC_SliderOuterGain ) )
|
|
|
|
{
|
|
|
|
m_OuterGain = ConvertLinearSliderPosToLogScale( nPos ) / 100.0f;
|
|
|
|
}
|
|
|
|
UpdateData( false );
|
|
|
|
DrawCones();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnPaint()
|
|
|
|
{
|
|
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
|
|
|
|
float innerangle = degToRad((float)m_InnerAngleDeg);
|
|
|
|
float outerangle = degToRad((float)m_OuterAngleDeg);
|
|
|
|
|
|
|
|
/*// Erase background (done by InvalidateRect())
|
|
|
|
CRect rect( XCenter-Radius, YCenter-Radius, XCenter+Radius+1, YCenter+Radius+1 );
|
|
|
|
CBrush brush;
|
|
|
|
brush.CreateSolidBrush( GetSysColor( COLOR_BTNFACE ) );
|
|
|
|
dc.FillRect( &rect, &brush );*/
|
|
|
|
|
|
|
|
if ( m_Pos3D )
|
|
|
|
{
|
|
|
|
COLORREF innercolor = RGB(255,0,0);
|
|
|
|
uint8 c = (uint)(255.0f * (1.0f - (float)(ConvertLogScaleToLinearSliderPosTo( m_OuterGain*100.0f ))/40.0f )); // linear, not logarithmic
|
|
|
|
COLORREF outercolor = RGB(255,c,c);
|
|
|
|
COLORREF tcolor = RGB(255,c/1.5,c/1.5); // not progressive
|
|
|
|
if ( m_OuterGain == 0.0f ) // change white to background color
|
|
|
|
{
|
|
|
|
outercolor = GetSysColor( COLOR_BTNFACE );
|
|
|
|
}
|
|
|
|
|
|
|
|
uint dx = (uint)(Radius*sin(outerangle/2.0f));
|
|
|
|
uint y = YCenter-(uint)(Radius*cos(outerangle/2.0f));
|
|
|
|
|
|
|
|
// Outside
|
|
|
|
CPen outpen( PS_SOLID, 1, outercolor );
|
|
|
|
CBrush outbrush;
|
|
|
|
outbrush.CreateSolidBrush( outercolor );
|
|
|
|
dc.SelectObject( &outpen );
|
|
|
|
dc.SelectObject( &outbrush );
|
|
|
|
dc.Pie( XCenter-Radius, YCenter-Radius, XCenter+Radius+1, YCenter+Radius+1, XCenter-dx, y, XCenter+dx, y );
|
|
|
|
|
|
|
|
// Transition
|
|
|
|
if ( (dx != 0) || (outerangle > 3.14) )
|
|
|
|
{
|
|
|
|
CPen tpen( PS_SOLID, 1, tcolor );
|
|
|
|
CBrush tbrush;
|
|
|
|
tbrush.CreateSolidBrush( tcolor );
|
|
|
|
dc.SelectObject( &tpen );
|
|
|
|
dc.SelectObject( &tbrush );
|
|
|
|
dc.Pie( XCenter-Radius, YCenter-Radius, XCenter+Radius+1, YCenter+Radius+1, XCenter+dx, y, XCenter-dx, y );
|
|
|
|
}
|
|
|
|
|
|
|
|
dx = (uint)(Radius*sin(innerangle/2.0f));
|
|
|
|
y = YCenter-(uint)(Radius*cos(innerangle/2.0f));
|
|
|
|
|
|
|
|
// Inner
|
|
|
|
if ( (dx != 0) || (innerangle > 3.14) )
|
|
|
|
{
|
|
|
|
CPen inpen( PS_SOLID, 1, innercolor );
|
|
|
|
CBrush inbrush;
|
|
|
|
inbrush.CreateSolidBrush( innercolor );
|
|
|
|
dc.SelectObject( &inpen );
|
|
|
|
dc.SelectObject( &inbrush );
|
|
|
|
dc.Pie( XCenter-Radius, YCenter-Radius, XCenter+Radius+1, YCenter+Radius+1, XCenter+dx, y, XCenter-dx, y );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
BOOL CSoundPage::DestroyWindow()
|
|
|
|
{
|
|
|
|
delete _NameFont;
|
|
|
|
|
|
|
|
return CDialog::DestroyWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void CSoundPage::OnButtonHelp()
|
|
|
|
{
|
|
|
|
MessageBox( "\
|
|
|
|
Gain: Range: [0, 1]. A gain factor is logarithmic ; 1.0 means no attenuation (full volume) ; 0.5 \
|
|
|
|
means an attenuation of 6 dB ; 0 means silence.\n\n\
|
|
|
|
Pitch: Range: ]0, 1]. 1.0 means normal ; dividing by 2 means pitching one octave down. Pitching up \
|
|
|
|
is not supported. 0 is not a legal value.\n\n\
|
|
|
|
Min Dist: Distance threshold below which gain is clamped (does not increase anymore).\n\
|
|
|
|
Unit: meters. Range: 0 - 1000000 (the maximum value 1e+006 is considered as infinite).\n\n\
|
|
|
|
Max Dist: Distance threshold above which gain is clamped (does not decrease anymore).\n\
|
|
|
|
Unit: meters. Range: 0 - 1000000 m (the maximum value 1e+006 is considered as infinite).\n\n\
|
|
|
|
Cone Inner Angle: Inside angle of the sound cone where the main gain is applied. \
|
|
|
|
The default of 360 means that the inner angle covers the entire world, which is equivalent to \
|
|
|
|
an omnidirectional source.\n\
|
|
|
|
Unit: degrees. Range: 0 - 360.\n\n\
|
|
|
|
Cone Outer Angle: Outer angle of the sound cone where the outer gain is applied \
|
|
|
|
to the main gain. The default of 360 means that the outer angle covers the entire world. If \
|
|
|
|
the inner angle is also 360, then there is no transition zone for angle-dependent (progressive) \
|
|
|
|
attenuation.\n\
|
|
|
|
Unit: degress. Range: 0 - 360.\n\n\
|
|
|
|
Cone Outer Gain: The factor with which the main gain is multiplied to determine the effective \
|
|
|
|
gain outside the cone defined by the outer angle. To test the outer gain, you can play the \
|
|
|
|
sound source as if you were outside the cone.\n\
|
|
|
|
Range: 0 - 1.\
|
|
|
|
", "Help about types" );
|
|
|
|
}
|
|
|
|
|