first finished version of stereo support (incl. GUI and settings)
This commit is contained in:
parent
2a77dbda58
commit
b710dfbc72
7 changed files with 147 additions and 59 deletions
|
@ -1,5 +1,7 @@
|
|||
3.1.1
|
||||
|
||||
- added stereo audio channel support
|
||||
|
||||
- added input/output audio channel mapping for ASIO audio interface
|
||||
|
||||
|
||||
|
|
145
src/client.cpp
145
src/client.cpp
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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() )
|
||||
|
|
Loading…
Reference in a new issue