first finished version of stereo support (incl. GUI and settings)

This commit is contained in:
Volker Fischer 2010-03-22 19:01:41 +00:00
parent 2a77dbda58
commit b710dfbc72
7 changed files with 147 additions and 59 deletions

View file

@ -1,5 +1,7 @@
3.1.1
- added stereo audio channel support
- added input/output audio channel mapping for ASIO audio interface

View file

@ -51,7 +51,7 @@ CClient::CClient ( const quint16 iPortNumber ) :
bFraSiFactSafeSupported ( false ),
iCeltNumCodedBytes ( CELT_NUM_BYTES_MONO_NORMAL_QUALITY ),
bCeltDoHighQuality ( false ),
bStereo ( false ),
bUseStereo ( false ),
bSndCrdConversionBufferRequired ( false ),
iSndCardMonoBlockSizeSamConvBuff ( 0 )
{
@ -234,8 +234,26 @@ void CClient::SetCELTHighQuality ( const bool bNCeltHighQualityFlag )
// set new parameter
bCeltDoHighQuality = bNCeltHighQualityFlag;
Init();
// init with new block size index parameter
if ( bWasRunning )
{
Sound.Start();
}
}
void CClient::SetUseStereo ( const bool bNUseStereo )
{
// init with new parameter, if client was running then first
// stop it and restart again after new initialization
const bool bWasRunning = Sound.IsRunning();
if ( bWasRunning )
{
Sound.Stop();
}
// set new parameter
bUseStereo = bNUseStereo;
Init();
if ( bWasRunning )
@ -496,9 +514,8 @@ void CClient::Init()
// calculate stereo (two channels) buffer size
iStereoBlockSizeSam = 2 * iMonoBlockSizeSam;
vecsAudioSndCrdMono.Init ( iMonoBlockSizeSam );
vecsAudioSndCrdStereo.Init ( iStereoBlockSizeSam );
vecdAudioStereo.Init ( iStereoBlockSizeSam );
vecsAudioSndCrdMono.Init ( iMonoBlockSizeSam );
vecdAudioStereo.Init ( iStereoBlockSizeSam );
// init response time evaluation
CycleTimeVariance.Init ( iMonoBlockSizeSam,
@ -512,7 +529,7 @@ void CClient::Init()
// inits for CELT coding
if ( bCeltDoHighQuality )
{
if ( bStereo )
if ( bUseStereo )
{
iCeltNumCodedBytes = CELT_NUM_BYTES_STEREO_HIGH_QUALITY;
}
@ -523,7 +540,7 @@ void CClient::Init()
}
else
{
if ( bStereo )
if ( bUseStereo )
{
iCeltNumCodedBytes = CELT_NUM_BYTES_STEREO_NORMAL_QUALITY;
}
@ -536,7 +553,7 @@ void CClient::Init()
// inits for network and channel
vecbyNetwData.Init ( iCeltNumCodedBytes );
if ( bStereo )
if ( bUseStereo )
{
vecsNetwork.Init ( iStereoBlockSizeSam );
@ -641,7 +658,7 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
// from double to short
if ( iAudioInFader == AUD_FADER_IN_MIDDLE )
{
if ( bStereo )
if ( bUseStereo )
{
// perform type conversion
for ( i = 0; i < iStereoBlockSizeSam; i++ )
@ -662,52 +679,78 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
}
else
{
// TODO for stereo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// TODO for stereo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// TODO for stereo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// TODO for stereo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// TODO for stereo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// TODO for stereo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// make sure that in the middle position the two channels are
// amplified by 1/2, if the pan is set to one channel, this
// channel should have an amplification of 1
const double dAttFact = static_cast<double> (
AUD_FADER_IN_MIDDLE - abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
AUD_FADER_IN_MIDDLE / 2;
const double dAmplFact = 0.5 + static_cast<double> (
abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
AUD_FADER_IN_MIDDLE / 2;
if ( iAudioInFader > AUD_FADER_IN_MIDDLE )
if ( bUseStereo )
{
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
// stereo
const double dAttFactStereo = static_cast<double> (
AUD_FADER_IN_MIDDLE - abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
AUD_FADER_IN_MIDDLE;
if ( iAudioInFader > AUD_FADER_IN_MIDDLE )
{
// attenuation on right channel
vecsNetwork[i] = Double2Short (
dAmplFact * vecdAudioStereo[j] +
dAttFact * vecdAudioStereo[j + 1] );
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
{
// attenuation on right channel
vecsNetwork[j] = Double2Short (
vecdAudioStereo[j] );
vecsNetwork[j + 1] = Double2Short (
dAttFactStereo * vecdAudioStereo[j + 1] );
}
}
else
{
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
{
// attenuation on left channel
vecsNetwork[j] = Double2Short (
dAttFactStereo * vecdAudioStereo[j] );
vecsNetwork[j + 1] = Double2Short (
vecdAudioStereo[j + 1] );
}
}
}
else
{
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
// mono
// make sure that in the middle position the two channels are
// amplified by 1/2, if the pan is set to one channel, this
// channel should have an amplification of 1
const double dAttFactMono = static_cast<double> (
AUD_FADER_IN_MIDDLE - abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
AUD_FADER_IN_MIDDLE / 2;
const double dAmplFactMono = 0.5 + static_cast<double> (
abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
AUD_FADER_IN_MIDDLE / 2;
if ( iAudioInFader > AUD_FADER_IN_MIDDLE )
{
// attenuation on left channel
vecsNetwork[i] = Double2Short (
dAmplFact * vecdAudioStereo[j + 1] +
dAttFact * vecdAudioStereo[j] );
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
{
// attenuation on right channel
vecsNetwork[i] = Double2Short (
dAmplFactMono * vecdAudioStereo[j] +
dAttFactMono * vecdAudioStereo[j + 1] );
}
}
else
{
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
{
// attenuation on left channel
vecsNetwork[i] = Double2Short (
dAmplFactMono * vecdAudioStereo[j + 1] +
dAttFactMono * vecdAudioStereo[j] );
}
}
}
}
for ( i = 0; i < iSndCrdFrameSizeFactor; i++ )
{
if ( bStereo )
if ( bUseStereo )
{
// encode current audio frame with CELT encoder
celt_encode ( CeltEncoderStereo,
@ -751,12 +794,12 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
// CELT decoding
if ( bReceiveDataOk )
{
if ( bStereo )
if ( bUseStereo )
{
celt_decode ( CeltDecoderStereo,
&vecbyNetwData[0],
iCeltNumCodedBytes,
&vecsAudioSndCrdStereo[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
}
else
{
@ -769,12 +812,12 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
else
{
// lost packet
if ( bStereo )
if ( bUseStereo )
{
celt_decode ( CeltDecoderStereo,
NULL,
0,
&vecsAudioSndCrdStereo[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
}
else
{
@ -789,15 +832,7 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
// check if channel is connected
if ( Channel.IsConnected() )
{
if ( bStereo )
{
// copy data
for ( i = 0; i < iStereoBlockSizeSam; i++ )
{
vecsStereoSndCrd[i] = vecsAudioSndCrdStereo[i];
}
}
else
if ( !bUseStereo )
{
// copy mono data in stereo sound card buffer
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )

View file

@ -104,6 +104,9 @@ public:
bool GetCELTHighQuality() const { return bCeltDoHighQuality; }
void SetCELTHighQuality ( const bool bNCeltHighQualityFlag );
bool GetUseStereo() const { return bUseStereo; }
void SetUseStereo ( const bool bNUseStereo );
int GetAudioInFader() const { return iAudioInFader; }
void SetAudioInFader ( const int iNV ) { iAudioInFader = iNV; }
@ -236,7 +239,7 @@ protected:
CELTDecoder* CeltDecoderStereo;
int iCeltNumCodedBytes;
bool bCeltDoHighQuality;
bool bStereo;
bool bUseStereo;
CVector<unsigned char> vecCeltData;
CSocket Socket;
@ -270,7 +273,6 @@ protected:
EGUIDesign eGUIDesign;
CVector<int16_t> vecsAudioSndCrdMono;
CVector<int16_t> vecsAudioSndCrdStereo;
CVector<double> vecdAudioStereo;
CVector<int16_t> vecsNetwork;

View file

@ -182,6 +182,15 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
cbUseHighQualityAudio->setAccessibleName ( tr ( "Use high quality audio "
"check box" ) );
// use stereo
cbUseStereo->setWhatsThis ( tr ( "<b>Stereo</b> "
"Enables the stereo mode. If not checked, a mono mode is used. "
"Enabling stereo mode will increase the stream data rate. Make sure "
"that the current upload rate does not exceed the available bandwidth "
"of your internet connection." ) );
cbUseStereo->setAccessibleName ( tr ( "Stereo check box" ) );
// current connection status parameter
QString strConnStats = tr ( "<b>Current Connection Status "
"Parameter:</b> The ping time is the time required for the audio "
@ -283,6 +292,16 @@ cbGUIDesignFancy->setVisible ( false );
cbUseHighQualityAudio->setCheckState ( Qt::Unchecked );
}
// "Stereo" check box
if ( pClient->GetUseStereo() )
{
cbUseStereo->setCheckState ( Qt::Checked );
}
else
{
cbUseStereo->setCheckState ( Qt::Unchecked );
}
// set text for sound card buffer delay radio buttons
rButBufferDelayPreferred->setText ( GenSndCrdBufferDelayString (
FRAME_SIZE_FACTOR_PREFERRED * SYSTEM_FRAME_SIZE_SAMPLES,
@ -325,6 +344,9 @@ cbGUIDesignFancy->setVisible ( false );
QObject::connect ( cbUseHighQualityAudio, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnUseHighQualityAudioStateChanged ( int ) ) );
QObject::connect ( cbUseStereo, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnUseStereoStateChanged ( int ) ) );
QObject::connect ( cbAutoJitBuf, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnAutoJitBuf ( int ) ) );
@ -572,7 +594,13 @@ void CClientSettingsDlg::OnGUIDesignFancyStateChanged ( int value )
void CClientSettingsDlg::OnUseHighQualityAudioStateChanged ( int value )
{
pClient->SetCELTHighQuality ( value == Qt::Checked );
UpdateDisplay();
UpdateDisplay(); // upload rate will be changed
}
void CClientSettingsDlg::OnUseStereoStateChanged ( int value )
{
pClient->SetUseStereo ( value == Qt::Checked );
UpdateDisplay(); // upload rate will be changed
}
void CClientSettingsDlg::OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* button )

View file

@ -90,6 +90,7 @@ protected:
void OnOpenChatOnNewMessageStateChanged ( int value );
void OnGUIDesignFancyStateChanged ( int value );
void OnUseHighQualityAudioStateChanged ( int value );
void OnUseStereoStateChanged ( int value );
void OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* button );
void OnPingTimeResult ( int iPingTime );
void OnSoundCrdSelection ( int iSndDevIdx );

View file

@ -432,6 +432,16 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbUseStereo" >
<property name="windowModality" >
<enum>Qt::NonModal</enum>
</property>
<property name="text" >
<string>Stereo</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
@ -440,7 +450,7 @@
<property name="sizeHint" >
<size>
<width>201</width>
<height>71</height>
<height>81</height>
</size>
</property>
</spacer>

View file

@ -189,6 +189,12 @@ void CSettings::ReadIniFile ( const QString& sFileName )
{
pClient->SetCELTHighQuality ( bValue );
}
// flag whether stereo mode is used
if ( GetFlagIniSet ( IniXMLDocument, "client", "stereoaudio", bValue ) )
{
pClient->SetUseStereo ( bValue );
}
}
void CSettings::WriteIniFile ( const QString& sFileName )
@ -266,6 +272,10 @@ void CSettings::WriteIniFile ( const QString& sFileName )
SetFlagIniSet ( IniXMLDocument, "client", "highqualityaudio",
pClient->GetCELTHighQuality() );
// flag whether stereo mode is used
SetFlagIniSet ( IniXMLDocument, "client", "stereoaudio",
pClient->GetUseStereo() );
// prepare file name for storing initialization data in XML file
QString sCurFileName = sFileName;
if ( sCurFileName.isEmpty() )