khanat-opennel-code/code/nel/tools/sound/source_sounds_builder/SoundPage.cpp
2013-06-08 14:56:58 +02:00

911 lines
20 KiB
C++

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