Merge pull request #145 from tarmoj/panning

Implemented panning for channels.
This commit is contained in:
Volker Fischer 2020-05-17 18:15:48 +02:00 committed by GitHub
commit ce7fd592bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 248 additions and 19 deletions

58
src/audiomixerboard.cpp Executable file → Normal file
View file

@ -40,6 +40,8 @@ CChannelFader::CChannelFader ( QWidget* pNW,
plbrChannelLevel = new CMultiColorLEDBar ( pLevelsBox ); plbrChannelLevel = new CMultiColorLEDBar ( pLevelsBox );
pFader = new QSlider ( Qt::Vertical, pLevelsBox ); pFader = new QSlider ( Qt::Vertical, pLevelsBox );
pPan = new QSlider (Qt::Horizontal, pLevelsBox);
pMuteSoloBox = new QWidget ( pFrame ); pMuteSoloBox = new QWidget ( pFrame );
pcbMute = new QCheckBox ( tr ( "Mute" ), pMuteSoloBox ); pcbMute = new QCheckBox ( tr ( "Mute" ), pMuteSoloBox );
pcbSolo = new QCheckBox ( tr ( "Solo" ), pMuteSoloBox ); pcbSolo = new QCheckBox ( tr ( "Solo" ), pMuteSoloBox );
@ -64,6 +66,11 @@ CChannelFader::CChannelFader ( QWidget* pNW,
pFader->setRange ( 0, AUD_MIX_FADER_MAX ); pFader->setRange ( 0, AUD_MIX_FADER_MAX );
pFader->setTickInterval ( AUD_MIX_FADER_MAX / 9 ); pFader->setTickInterval ( AUD_MIX_FADER_MAX / 9 );
// setup panning slider
pPan->setRange( 0, AUD_MIX_PAN_MAX);
pPan->setValue(AUD_MIX_PAN_MAX/2);
// setup fader tag label (black bold text which is centered) // setup fader tag label (black bold text which is centered)
plblLabel->setTextFormat ( Qt::PlainText ); plblLabel->setTextFormat ( Qt::PlainText );
plblLabel->setAlignment ( Qt::AlignHCenter | Qt::AlignVCenter ); plblLabel->setAlignment ( Qt::AlignHCenter | Qt::AlignVCenter );
@ -96,6 +103,7 @@ CChannelFader::CChannelFader ( QWidget* pNW,
pMuteSoloGrid->addWidget ( pcbMute, 0, Qt::AlignLeft ); pMuteSoloGrid->addWidget ( pcbMute, 0, Qt::AlignLeft );
pMuteSoloGrid->addWidget ( pcbSolo, 0, Qt::AlignLeft ); pMuteSoloGrid->addWidget ( pcbSolo, 0, Qt::AlignLeft );
pMainGrid->addWidget ( pPan, 0, Qt::AlignCenter );
pMainGrid->addWidget ( pLevelsBox, 0, Qt::AlignHCenter ); pMainGrid->addWidget ( pLevelsBox, 0, Qt::AlignHCenter );
pMainGrid->addWidget ( pMuteSoloBox, 0, Qt::AlignHCenter ); pMainGrid->addWidget ( pMuteSoloBox, 0, Qt::AlignHCenter );
pMainGrid->addWidget ( pLabelInstBox ); pMainGrid->addWidget ( pLabelInstBox );
@ -119,6 +127,10 @@ CChannelFader::CChannelFader ( QWidget* pNW,
pFader->setAccessibleName ( tr ( "Local mix level setting of the current audio " pFader->setAccessibleName ( tr ( "Local mix level setting of the current audio "
"channel at the server" ) ); "channel at the server" ) );
pPan->setWhatsThis ( "<b>" + tr ( "Panning") + ":</b>" + tr ( "Sets the panning position from Left to Right of the channel. "
" Works only in stero or preferably mono in/stereo out mode." ) );
pPan->setAccessibleName ( tr ( "Local panning position of the current audio channel at the server" ) );
pcbMute->setWhatsThis ( "<b>" + tr ( "Mute" ) + ":</b> " + tr ( pcbMute->setWhatsThis ( "<b>" + tr ( "Mute" ) + ":</b> " + tr (
"With the Mute checkbox, the audio channel can be muted." ) ); "With the Mute checkbox, the audio channel can be muted." ) );
pcbMute->setAccessibleName ( tr ( "Mute button" ) ); pcbMute->setAccessibleName ( tr ( "Mute button" ) );
@ -145,6 +157,9 @@ CChannelFader::CChannelFader ( QWidget* pNW,
QObject::connect ( pFader, SIGNAL ( valueChanged ( int ) ), QObject::connect ( pFader, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnLevelValueChanged ( int ) ) ); this, SLOT ( OnLevelValueChanged ( int ) ) );
QObject::connect ( pPan, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnPanValueChanged ( int ) ) );
QObject::connect ( pcbMute, SIGNAL ( stateChanged ( int ) ), QObject::connect ( pcbMute, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnMuteStateChanged ( int ) ) ); this, SLOT ( OnMuteStateChanged ( int ) ) );
@ -243,8 +258,9 @@ void CChannelFader::SetupFaderTag ( const ESkillLevel eSkillLevel )
void CChannelFader::Reset() void CChannelFader::Reset()
{ {
// init gain value -> maximum value as definition according to server // init gain and pan value -> maximum value as definition according to server
pFader->setValue ( AUD_MIX_FADER_MAX ); pFader->setValue ( AUD_MIX_FADER_MAX );
pPan->setValue ( AUD_MIX_PAN_MAX/2 );
// reset mute/solo check boxes and level meter // reset mute/solo check boxes and level meter
pcbMute->setChecked ( false ); pcbMute->setChecked ( false );
@ -279,6 +295,18 @@ void CChannelFader::SetFaderLevel ( const int iLevel )
// server about the change // server about the change
pFader->setValue ( iLevel ); pFader->setValue ( iLevel );
SendFaderLevelToServer ( iLevel ); SendFaderLevelToServer ( iLevel );
}
}
void CChannelFader::SetPanValue(const int iPan)
{
// first make a range check
if ( ( iPan >= 0 ) && ( iPan <= AUD_MIX_PAN_MAX ) )
{
// we set the new fader level in the GUI (slider control) and also tell the
// server about the change
pPan->setValue ( iPan );
SendPanValueToServer( iPan );
} }
} }
@ -307,6 +335,12 @@ void CChannelFader::SendFaderLevelToServer ( const int iLevel )
} }
} }
void CChannelFader::SendPanValueToServer ( const int iPan )
{
double dPan = static_cast<double> ( iPan ) / AUD_MIX_PAN_MAX;
emit panValueChanged ( dPan );
}
void CChannelFader::OnMuteStateChanged ( int value ) void CChannelFader::OnMuteStateChanged ( int value )
{ {
// call muting function // call muting function
@ -525,6 +559,7 @@ CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent, Qt::WindowFlags ) :
QScrollArea ( parent ), QScrollArea ( parent ),
vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ), vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ),
vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ), vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ),
vecStoredPanValues ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_PAN_MAX/2),
vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ),
vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ),
iNewClientFaderLevel ( 100 ), iNewClientFaderLevel ( 100 ),
@ -571,12 +606,18 @@ inline void CAudioMixerBoard::connectFaderSignalsToMixerBoardSlots()
void ( CAudioMixerBoard::* pGainValueChanged )( double ) = void ( CAudioMixerBoard::* pGainValueChanged )( double ) =
&CAudioMixerBoardSlots<slotId>::OnChGainValueChanged; &CAudioMixerBoardSlots<slotId>::OnChGainValueChanged;
void ( CAudioMixerBoard::* pPanValueChanged )( double ) =
&CAudioMixerBoardSlots<slotId>::OnChPanValueChanged;
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::soloStateChanged, QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::soloStateChanged,
this, &CAudioMixerBoard::UpdateSoloStates ); this, &CAudioMixerBoard::UpdateSoloStates );
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::gainValueChanged, QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::gainValueChanged,
this, pGainValueChanged ); this, pGainValueChanged );
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::panValueChanged,
this, pPanValueChanged );
connectFaderSignalsToMixerBoardSlots<slotId - 1>(); connectFaderSignalsToMixerBoardSlots<slotId - 1>();
}; };
@ -700,15 +741,18 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
// the text has actually changed, search in the list of // the text has actually changed, search in the list of
// stored settings if we have a matching entry // stored settings if we have a matching entry
int iStoredFaderLevel; int iStoredFaderLevel;
int iStoredPanValue;
bool bStoredFaderIsSolo; bool bStoredFaderIsSolo;
bool bStoredFaderIsMute; bool bStoredFaderIsMute;
if ( GetStoredFaderSettings ( vecChanInfo[j], if ( GetStoredFaderSettings ( vecChanInfo[j],
iStoredFaderLevel, iStoredFaderLevel,
iStoredPanValue,
bStoredFaderIsSolo, bStoredFaderIsSolo,
bStoredFaderIsMute ) ) bStoredFaderIsMute ) )
{ {
vecpChanFader[i]->SetFaderLevel ( iStoredFaderLevel ); vecpChanFader[i]->SetFaderLevel ( iStoredFaderLevel );
vecpChanFader[i]->SetPanValue ( iStoredPanValue );
vecpChanFader[i]->SetFaderIsSolo ( bStoredFaderIsSolo ); vecpChanFader[i]->SetFaderIsSolo ( bStoredFaderIsSolo );
vecpChanFader[i]->SetFaderIsMute ( bStoredFaderIsMute ); vecpChanFader[i]->SetFaderIsMute ( bStoredFaderIsMute );
} }
@ -789,6 +833,13 @@ void CAudioMixerBoard::UpdateGainValue ( const int iChannelIdx,
emit ChangeChanGain ( iChannelIdx, dValue ); emit ChangeChanGain ( iChannelIdx, dValue );
} }
void CAudioMixerBoard::UpdatePanValue ( const int iChannelIdx,
const double dValue )
{
emit ChangeChanPan ( iChannelIdx, dValue );
}
void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader ) void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
{ {
// if the fader was visible and the name is not empty, we store the old gain // if the fader was visible and the name is not empty, we store the old gain
@ -796,6 +847,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
!pChanFader->GetReceivedName().isEmpty() ) !pChanFader->GetReceivedName().isEmpty() )
{ {
CVector<int> viOldStoredFaderLevels ( vecStoredFaderLevels ); CVector<int> viOldStoredFaderLevels ( vecStoredFaderLevels );
CVector<int> viOldStoredPanValues ( vecStoredPanValues );
CVector<int> vbOldStoredFaderIsSolo ( vecStoredFaderIsSolo ); CVector<int> vbOldStoredFaderIsSolo ( vecStoredFaderIsSolo );
CVector<int> vbOldStoredFaderIsMute ( vecStoredFaderIsMute ); CVector<int> vbOldStoredFaderIsMute ( vecStoredFaderIsMute );
@ -809,6 +861,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
// current fader level and solo state is at the top of the list // current fader level and solo state is at the top of the list
vecStoredFaderLevels[0] = pChanFader->GetFaderLevel(); vecStoredFaderLevels[0] = pChanFader->GetFaderLevel();
vecStoredPanValues[0] = pChanFader->GetPanValue();
vecStoredFaderIsSolo[0] = pChanFader->IsSolo(); vecStoredFaderIsSolo[0] = pChanFader->IsSolo();
vecStoredFaderIsMute[0] = pChanFader->IsMute(); vecStoredFaderIsMute[0] = pChanFader->IsMute();
iTempListCnt = 1; iTempListCnt = 1;
@ -824,6 +877,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
if ( iIdx != iOldIdx ) if ( iIdx != iOldIdx )
{ {
vecStoredFaderLevels[iTempListCnt] = viOldStoredFaderLevels[iIdx]; vecStoredFaderLevels[iTempListCnt] = viOldStoredFaderLevels[iIdx];
vecStoredPanValues[iTempListCnt] = viOldStoredPanValues[iIdx];
vecStoredFaderIsSolo[iTempListCnt] = vbOldStoredFaderIsSolo[iIdx]; vecStoredFaderIsSolo[iTempListCnt] = vbOldStoredFaderIsSolo[iIdx];
vecStoredFaderIsMute[iTempListCnt] = vbOldStoredFaderIsMute[iIdx]; vecStoredFaderIsMute[iTempListCnt] = vbOldStoredFaderIsMute[iIdx];
@ -836,6 +890,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
bool CAudioMixerBoard::GetStoredFaderSettings ( const CChannelInfo& ChanInfo, bool CAudioMixerBoard::GetStoredFaderSettings ( const CChannelInfo& ChanInfo,
int& iStoredFaderLevel, int& iStoredFaderLevel,
int& iStoredPanValue,
bool& bStoredFaderIsSolo, bool& bStoredFaderIsSolo,
bool& bStoredFaderIsMute) bool& bStoredFaderIsMute)
{ {
@ -849,6 +904,7 @@ bool CAudioMixerBoard::GetStoredFaderSettings ( const CChannelInfo& ChanInfo,
{ {
// copy stored settings values // copy stored settings values
iStoredFaderLevel = vecStoredFaderLevels[iIdx]; iStoredFaderLevel = vecStoredFaderLevels[iIdx];
iStoredPanValue = vecStoredPanValues[iIdx];
bStoredFaderIsSolo = vecStoredFaderIsSolo[iIdx] != 0; bStoredFaderIsSolo = vecStoredFaderIsSolo[iIdx] != 0;
bStoredFaderIsMute = vecStoredFaderIsMute[iIdx] != 0; bStoredFaderIsMute = vecStoredFaderIsMute[iIdx] != 0;

19
src/audiomixerboard.h Executable file → Normal file
View file

@ -61,9 +61,11 @@ public:
void UpdateSoloState ( const bool bNewOtherSoloState ); void UpdateSoloState ( const bool bNewOtherSoloState );
void SetFaderLevel ( const int iLevel ); void SetFaderLevel ( const int iLevel );
void SetPanValue ( const int iPan );
void SetFaderIsSolo ( const bool bIsSolo ); void SetFaderIsSolo ( const bool bIsSolo );
void SetFaderIsMute ( const bool bIsMute ); void SetFaderIsMute ( const bool bIsMute );
int GetFaderLevel() { return pFader->value(); } int GetFaderLevel() { return pFader->value(); }
int GetPanValue() {return pPan->value(); }
void Reset(); void Reset();
void SetChannelLevel ( const uint16_t iLevel ); void SetChannelLevel ( const uint16_t iLevel );
@ -71,6 +73,7 @@ protected:
double CalcFaderGain ( const int value ); double CalcFaderGain ( const int value );
void SetMute ( const bool bState ); void SetMute ( const bool bState );
void SendFaderLevelToServer ( const int iLevel ); void SendFaderLevelToServer ( const int iLevel );
void SendPanValueToServer ( const int iPan );
void SetupFaderTag ( const ESkillLevel eSkillLevel ); void SetupFaderTag ( const ESkillLevel eSkillLevel );
QFrame* pFrame; QFrame* pFrame;
@ -79,6 +82,7 @@ protected:
QWidget* pMuteSoloBox; QWidget* pMuteSoloBox;
CMultiColorLEDBar* plbrChannelLevel; CMultiColorLEDBar* plbrChannelLevel;
QSlider* pFader; QSlider* pFader;
QSlider* pPan;
QCheckBox* pcbMute; QCheckBox* pcbMute;
QCheckBox* pcbSolo; QCheckBox* pcbSolo;
@ -94,10 +98,12 @@ protected:
public slots: public slots:
void OnLevelValueChanged ( int value ) { SendFaderLevelToServer ( value ); } void OnLevelValueChanged ( int value ) { SendFaderLevelToServer ( value ); }
void OnPanValueChanged ( int value ) {SendPanValueToServer ( value ); }
void OnMuteStateChanged ( int value ); void OnMuteStateChanged ( int value );
signals: signals:
void gainValueChanged ( double value ); void gainValueChanged ( double value );
void panValueChanged (double value );
void soloStateChanged ( int value ); void soloStateChanged ( int value );
}; };
@ -106,10 +112,13 @@ class CAudioMixerBoardSlots : public CAudioMixerBoardSlots<slotId - 1>
{ {
public: public:
void OnChGainValueChanged ( double dValue ) { UpdateGainValue ( slotId - 1, dValue ); } void OnChGainValueChanged ( double dValue ) { UpdateGainValue ( slotId - 1, dValue ); }
void OnChPanValueChanged ( double dValue ) { UpdatePanValue ( slotId - 1, dValue ); }
protected: protected:
virtual void UpdateGainValue ( const int iChannelIdx, virtual void UpdateGainValue ( const int iChannelIdx,
const double dValue ) = 0; const double dValue ) = 0;
virtual void UpdatePanValue ( const int iChannelIdx,
const double dValue ) = 0;
}; };
template<> template<>
@ -139,19 +148,24 @@ public:
// settings // settings
CVector<QString> vecStoredFaderTags; CVector<QString> vecStoredFaderTags;
CVector<int> vecStoredFaderLevels; CVector<int> vecStoredFaderLevels;
CVector<int> vecStoredPanValues;
CVector<int> vecStoredFaderIsSolo; CVector<int> vecStoredFaderIsSolo;
CVector<int> vecStoredFaderIsMute; CVector<int> vecStoredFaderIsMute;
int iNewClientFaderLevel; int iNewClientFaderLevel;
protected: protected:
bool GetStoredFaderSettings ( const CChannelInfo& ChanInfo, bool GetStoredFaderSettings (const CChannelInfo& ChanInfo,
int& iStoredFaderLevel, int& iStoredFaderLevel,
int& iStoredPanValue,
bool& bStoredFaderIsSolo, bool& bStoredFaderIsSolo,
bool& bStoredFaderIsMute ); bool& bStoredFaderIsMute );
void StoreFaderSettings ( CChannelFader* pChanFader ); void StoreFaderSettings ( CChannelFader* pChanFader );
void UpdateSoloStates(); void UpdateSoloStates();
void OnGainValueChanged ( const int iChannelIdx,
const double dValue );
CVector<CChannelFader*> vecpChanFader; CVector<CChannelFader*> vecpChanFader;
QGroupBox* pGroupBox; QGroupBox* pGroupBox;
QHBoxLayout* pMainLayout; QHBoxLayout* pMainLayout;
@ -161,11 +175,14 @@ protected:
virtual void UpdateGainValue ( const int iChannelIdx, virtual void UpdateGainValue ( const int iChannelIdx,
const double dValue ); const double dValue );
virtual void UpdatePanValue ( const int iChannelIdx,
const double dValue );
template<unsigned int slotId> template<unsigned int slotId>
inline void connectFaderSignalsToMixerBoardSlots(); inline void connectFaderSignalsToMixerBoardSlots();
signals: signals:
void ChangeChanGain ( int iId, double dGain ); void ChangeChanGain ( int iId, double dGain );
void ChangeChanPan ( int iId, double dPan );
void NumClientsChanged ( int iNewNumClients ); void NumClientsChanged ( int iNewNumClients );
}; };

View file

@ -28,6 +28,7 @@
// CChannel implementation ***************************************************** // CChannel implementation *****************************************************
CChannel::CChannel ( const bool bNIsServer ) : CChannel::CChannel ( const bool bNIsServer ) :
vecdGains ( MAX_NUM_CHANNELS, 1.0 ), vecdGains ( MAX_NUM_CHANNELS, 1.0 ),
vecdPannings ( MAX_NUM_CHANNELS, 0.5),
bDoAutoSockBufSize ( true ), bDoAutoSockBufSize ( true ),
iFadeInCnt ( 0 ), iFadeInCnt ( 0 ),
iFadeInCntMax ( FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE ), iFadeInCntMax ( FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE ),
@ -86,6 +87,9 @@ qRegisterMetaType<CHostAddress> ( "CHostAddress" );
QObject::connect( &Protocol, SIGNAL ( ChangeChanGain ( int, double ) ), QObject::connect( &Protocol, SIGNAL ( ChangeChanGain ( int, double ) ),
this, SLOT ( OnChangeChanGain ( int, double ) ) ); this, SLOT ( OnChangeChanGain ( int, double ) ) );
QObject::connect( &Protocol, SIGNAL ( ChangeChanPan ( int, double ) ),
this, SLOT ( OnChangeChanPan ( int, double ) ) );
QObject::connect( &Protocol, SIGNAL ( ChangeChanInfo ( CChannelCoreInfo ) ), QObject::connect( &Protocol, SIGNAL ( ChangeChanInfo ( CChannelCoreInfo ) ),
this, SLOT ( OnChangeChanInfo ( CChannelCoreInfo ) ) ); this, SLOT ( OnChangeChanInfo ( CChannelCoreInfo ) ) );
@ -269,6 +273,32 @@ double CChannel::GetGain ( const int iChanID )
} }
} }
void CChannel::SetPan(const int iChanID, const double dNewPan)
{
QMutexLocker locker ( &Mutex );
// set value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
{
vecdPannings[iChanID] = dNewPan;
}
}
double CChannel::GetPan(const int iChanID)
{
QMutexLocker locker ( &Mutex );
// get value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
{
return vecdPannings[iChanID];
}
else
{
return 0;
}
}
void CChannel::SetChanInfo ( const CChannelCoreInfo& NChanInf ) void CChannel::SetChanInfo ( const CChannelCoreInfo& NChanInf )
{ {
// apply value (if different from previous one) // apply value (if different from previous one)
@ -335,6 +365,12 @@ void CChannel::OnChangeChanGain ( int iChanID,
SetGain ( iChanID, dNewGain ); SetGain ( iChanID, dNewGain );
} }
void CChannel::OnChangeChanPan ( int iChanID,
double dNewPan )
{
SetPan( iChanID, dNewPan );
}
void CChannel::OnChangeChanInfo ( CChannelCoreInfo ChanInfo ) void CChannel::OnChangeChanInfo ( CChannelCoreInfo ChanInfo )
{ {
SetChanInfo ( ChanInfo ); SetChanInfo ( ChanInfo );

View file

@ -110,9 +110,15 @@ public:
double GetGain ( const int iChanID ); double GetGain ( const int iChanID );
double GetFadeInGain() { return static_cast<double> ( iFadeInCnt ) / iFadeInCntMax; } double GetFadeInGain() { return static_cast<double> ( iFadeInCnt ) / iFadeInCntMax; }
void SetPan ( const int iChanID, const double dNewPan );
double GetPan ( const int iChanID );
void SetRemoteChanGain ( const int iId, const double dGain ) void SetRemoteChanGain ( const int iId, const double dGain )
{ Protocol.CreateChanGainMes ( iId, dGain ); } { Protocol.CreateChanGainMes ( iId, dGain ); }
void SetRemoteChanPan ( const int iId, const double dPan )
{ Protocol.CreateChanPanMes ( iId, dPan ); }
bool SetSockBufNumFrames ( const int iNewNumFrames, bool SetSockBufNumFrames ( const int iNewNumFrames,
const bool bPreserve = false ); const bool bPreserve = false );
int GetSockBufNumFrames() const { return iCurSockBufNumFrames; } int GetSockBufNumFrames() const { return iCurSockBufNumFrames; }
@ -191,6 +197,8 @@ protected:
// mixer and effect settings // mixer and effect settings
CVector<double> vecdGains; CVector<double> vecdGains;
CVector<double> vecdPannings;
// network jitter-buffer // network jitter-buffer
CNetBufWithStats SockBuf; CNetBufWithStats SockBuf;
int iCurSockBufNumFrames; int iCurSockBufNumFrames;
@ -228,6 +236,7 @@ public slots:
void OnSendProtMessage ( CVector<uint8_t> vecMessage ); void OnSendProtMessage ( CVector<uint8_t> vecMessage );
void OnJittBufSizeChange ( int iNewJitBufSize ); void OnJittBufSizeChange ( int iNewJitBufSize );
void OnChangeChanGain ( int iChanID, double dNewGain ); void OnChangeChanGain ( int iChanID, double dNewGain );
void OnChangeChanPan ( int iChanID, double dNewPan );
void OnChangeChanInfo ( CChannelCoreInfo ChanInfo ); void OnChangeChanInfo ( CChannelCoreInfo ChanInfo );
void OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps ); void OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps );
void OnReqNetTranspProps(); void OnReqNetTranspProps();

View file

@ -35,6 +35,7 @@ CClient::CClient ( const quint16 iPortNumber,
ChannelInfo (), ChannelInfo (),
vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ), vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ),
vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ), vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ),
vecStoredPanValues ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_PAN_MAX/2 ),
vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ),
vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ),
iNewClientFaderLevel ( 100 ), iNewClientFaderLevel ( 100 ),

View file

@ -245,6 +245,9 @@ public:
void SetRemoteChanGain ( const int iId, const double dGain ) void SetRemoteChanGain ( const int iId, const double dGain )
{ Channel.SetRemoteChanGain ( iId, dGain ); } { Channel.SetRemoteChanGain ( iId, dGain ); }
void SetRemoteChanPan ( const int iId, const double dPan )
{ Channel.SetRemoteChanPan ( iId, dPan ); }
void SetRemoteInfo() { Channel.SetRemoteInfo ( ChannelInfo ); } void SetRemoteInfo() { Channel.SetRemoteInfo ( ChannelInfo ); }
void CreateChatTextMes ( const QString& strChatText ) void CreateChatTextMes ( const QString& strChatText )
@ -279,6 +282,7 @@ public:
CChannelCoreInfo ChannelInfo; CChannelCoreInfo ChannelInfo;
CVector<QString> vecStoredFaderTags; CVector<QString> vecStoredFaderTags;
CVector<int> vecStoredFaderLevels; CVector<int> vecStoredFaderLevels;
CVector<int> vecStoredPanValues;
CVector<int> vecStoredFaderIsSolo; CVector<int> vecStoredFaderIsSolo;
CVector<int> vecStoredFaderIsMute; CVector<int> vecStoredFaderIsMute;
int iNewClientFaderLevel; int iNewClientFaderLevel;

View file

@ -193,6 +193,7 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
// restore fader settings // restore fader settings
MainMixerBoard->vecStoredFaderTags = pClient->vecStoredFaderTags; MainMixerBoard->vecStoredFaderTags = pClient->vecStoredFaderTags;
MainMixerBoard->vecStoredFaderLevels = pClient->vecStoredFaderLevels; MainMixerBoard->vecStoredFaderLevels = pClient->vecStoredFaderLevels;
MainMixerBoard->vecStoredPanValues = pClient->vecStoredPanValues;
MainMixerBoard->vecStoredFaderIsSolo = pClient->vecStoredFaderIsSolo; MainMixerBoard->vecStoredFaderIsSolo = pClient->vecStoredFaderIsSolo;
MainMixerBoard->vecStoredFaderIsMute = pClient->vecStoredFaderIsMute; MainMixerBoard->vecStoredFaderIsMute = pClient->vecStoredFaderIsMute;
MainMixerBoard->iNewClientFaderLevel = pClient->iNewClientFaderLevel; MainMixerBoard->iNewClientFaderLevel = pClient->iNewClientFaderLevel;
@ -521,6 +522,9 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ), QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ),
this, SLOT ( OnChangeChanGain ( int, double ) ) ); this, SLOT ( OnChangeChanGain ( int, double ) ) );
QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanPan ( int, double ) ),
this, SLOT ( OnChangeChanPan ( int, double ) ) );
QObject::connect ( MainMixerBoard, SIGNAL ( NumClientsChanged ( int ) ), QObject::connect ( MainMixerBoard, SIGNAL ( NumClientsChanged ( int ) ),
this, SLOT ( OnNumClientsChanged ( int ) ) ); this, SLOT ( OnNumClientsChanged ( int ) ) );
@ -585,6 +589,7 @@ void CClientDlg::closeEvent ( QCloseEvent* Event )
MainMixerBoard->HideAll(); MainMixerBoard->HideAll();
pClient->vecStoredFaderTags = MainMixerBoard->vecStoredFaderTags; pClient->vecStoredFaderTags = MainMixerBoard->vecStoredFaderTags;
pClient->vecStoredFaderLevels = MainMixerBoard->vecStoredFaderLevels; pClient->vecStoredFaderLevels = MainMixerBoard->vecStoredFaderLevels;
pClient->vecStoredPanValues = MainMixerBoard->vecStoredPanValues;
pClient->vecStoredFaderIsSolo = MainMixerBoard->vecStoredFaderIsSolo; pClient->vecStoredFaderIsSolo = MainMixerBoard->vecStoredFaderIsSolo;
pClient->vecStoredFaderIsMute = MainMixerBoard->vecStoredFaderIsMute; pClient->vecStoredFaderIsMute = MainMixerBoard->vecStoredFaderIsMute;
pClient->iNewClientFaderLevel = MainMixerBoard->iNewClientFaderLevel; pClient->iNewClientFaderLevel = MainMixerBoard->iNewClientFaderLevel;

View file

@ -166,6 +166,9 @@ public slots:
void OnChangeChanGain ( int iId, double dGain ) void OnChangeChanGain ( int iId, double dGain )
{ pClient->SetRemoteChanGain ( iId, dGain ); } { pClient->SetRemoteChanGain ( iId, dGain ); }
void OnChangeChanPan ( int iId, double dPan )
{ pClient->SetRemoteChanPan ( iId, dPan ); }
void OnNewLocalInputText ( QString strChatText ) void OnNewLocalInputText ( QString strChatText )
{ pClient->CreateChatTextMes ( strChatText ); } { pClient->CreateChatTextMes ( strChatText ); }

View file

@ -150,6 +150,11 @@ LED bar: lbr
// audio mixer fader maximum value // audio mixer fader maximum value
#define AUD_MIX_FADER_MAX 100 #define AUD_MIX_FADER_MAX 100
// audio mixer panning maximum value
#define AUD_MIX_PAN_MAX 100
// maximum number of recognized sound cards installed in the system, // maximum number of recognized sound cards installed in the system,
// definition for "no device" // definition for "no device"
#define MAX_NUMBER_SOUND_CARDS 129 // e.g. 16 inputs, 8 outputs + default entry (MacOS) #define MAX_NUMBER_SOUND_CARDS 129 // e.g. 16 inputs, 8 outputs + default entry (MacOS)

View file

@ -64,6 +64,13 @@ MESSAGES (with connection)
+-------------------+--------------+ +-------------------+--------------+
- PROTMESSID_CHANNEL_PAN: Gain of channel
+-------------------+-----------------+
| 1 byte channel ID | 2 bytes panning |
+-------------------+-----------------+
- PROTMESSID_CONN_CLIENTS_LIST: Information about connected clients - PROTMESSID_CONN_CLIENTS_LIST: Information about connected clients
for each connected client append following data: for each connected client append following data:
@ -573,6 +580,10 @@ if ( rand() < ( RAND_MAX / 2 ) ) return false;
bRet = EvaluateChanGainMes ( vecbyMesBodyData ); bRet = EvaluateChanGainMes ( vecbyMesBodyData );
break; break;
case PROTMESSID_CHANNEL_PAN:
bRet = EvaluateChanPanMes ( vecbyMesBodyData );
break;
case PROTMESSID_CONN_CLIENTS_LIST: case PROTMESSID_CONN_CLIENTS_LIST:
bRet = EvaluateConClientListMes ( vecbyMesBodyData ); bRet = EvaluateConClientListMes ( vecbyMesBodyData );
break; break;
@ -784,6 +795,23 @@ void CProtocol::CreateChanGainMes ( const int iChanID, const double dGain )
CreateAndSendMessage ( PROTMESSID_CHANNEL_GAIN, vecData ); CreateAndSendMessage ( PROTMESSID_CHANNEL_GAIN, vecData );
} }
void CProtocol::CreateChanPanMes(const int iChanID, const double dPan)
{
CVector<uint8_t> vecData ( 3 ); // 3 bytes of data
int iPos = 0; // init position pointer
// build data vector
// channel ID
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iChanID ), 1 );
// actual gain, we convert from double with range 0..1 to integer
const int iCurPan = static_cast<int> ( dPan * ( 1 << 15 ) );
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iCurPan ), 2 );
CreateAndSendMessage ( PROTMESSID_CHANNEL_PAN, vecData );
}
bool CProtocol::EvaluateChanGainMes ( const CVector<uint8_t>& vecData ) bool CProtocol::EvaluateChanGainMes ( const CVector<uint8_t>& vecData )
{ {
int iPos = 0; // init position pointer int iPos = 0; // init position pointer
@ -811,6 +839,33 @@ bool CProtocol::EvaluateChanGainMes ( const CVector<uint8_t>& vecData )
return false; // no error return false; // no error
} }
bool CProtocol::EvaluateChanPanMes(const CVector<uint8_t> &vecData)
{
int iPos = 0; // init position pointer
// check size
if ( vecData.Size() != 3 )
{
return true; // return error code
}
// channel ID
const int iCurID =
static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
// pan (read integer value)
const int iData =
static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
// we convert the gain from integer to double with range 0..1
const double dNewPan = static_cast<double> ( iData ) / ( 1 << 15 );
// invoke message action
emit ChangeChanPan ( iCurID, dNewPan );
return false; // no error
}
void CProtocol::CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo ) void CProtocol::CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo )
{ {
const int iNumClients = vecChanInfo.Size(); const int iNumClients = vecChanInfo.Size();

View file

@ -55,6 +55,7 @@
#define PROTMESSID_OPUS_SUPPORTED 26 // tells that OPUS codec is supported #define PROTMESSID_OPUS_SUPPORTED 26 // tells that OPUS codec is supported
#define PROTMESSID_LICENCE_REQUIRED 27 // licence required #define PROTMESSID_LICENCE_REQUIRED 27 // licence required
#define PROTMESSID_REQ_CHANNEL_LEVEL_LIST 28 // request the channel level list #define PROTMESSID_REQ_CHANNEL_LEVEL_LIST 28 // request the channel level list
#define PROTMESSID_CHANNEL_PAN 29 // set channel gain for mix
// message IDs of connection less messages (CLM) // message IDs of connection less messages (CLM)
// DEFINITION -> start at 1000, end at 1999, see IsConnectionLessMessageID // DEFINITION -> start at 1000, end at 1999, see IsConnectionLessMessageID
@ -96,6 +97,7 @@ public:
void CreateJitBufMes ( const int iJitBufSize ); void CreateJitBufMes ( const int iJitBufSize );
void CreateReqJitBufMes(); void CreateReqJitBufMes();
void CreateChanGainMes ( const int iChanID, const double dGain ); void CreateChanGainMes ( const int iChanID, const double dGain );
void CreateChanPanMes ( const int iChanID, const double dPan );
void CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo ); void CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo );
void CreateReqConnClientsList(); void CreateReqConnClientsList();
void CreateChanInfoMes ( const CChannelCoreInfo ChanInfo ); void CreateChanInfoMes ( const CChannelCoreInfo ChanInfo );
@ -218,6 +220,7 @@ protected:
bool EvaluateJitBufMes ( const CVector<uint8_t>& vecData ); bool EvaluateJitBufMes ( const CVector<uint8_t>& vecData );
bool EvaluateReqJitBufMes(); bool EvaluateReqJitBufMes();
bool EvaluateChanGainMes ( const CVector<uint8_t>& vecData ); bool EvaluateChanGainMes ( const CVector<uint8_t>& vecData );
bool EvaluateChanPanMes ( const CVector<uint8_t>& vecData );
bool EvaluateConClientListMes ( const CVector<uint8_t>& vecData ); bool EvaluateConClientListMes ( const CVector<uint8_t>& vecData );
bool EvaluateReqConnClientsList(); bool EvaluateReqConnClientsList();
bool EvaluateChanInfoMes ( const CVector<uint8_t>& vecData ); bool EvaluateChanInfoMes ( const CVector<uint8_t>& vecData );
@ -276,6 +279,7 @@ signals:
void ReqJittBufSize(); void ReqJittBufSize();
void ChangeNetwBlSiFact ( int iNewNetwBlSiFact ); void ChangeNetwBlSiFact ( int iNewNetwBlSiFact );
void ChangeChanGain ( int iChanID, double dNewGain ); void ChangeChanGain ( int iChanID, double dNewGain );
void ChangeChanPan ( int iChanID, double dNewPan );
void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo ); void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
void ServerFullMesReceived(); void ServerFullMesReceived();
void ReqConnClientsList(); void ReqConnClientsList();

View file

@ -340,6 +340,7 @@ CServer::CServer ( const int iNewMaxNumChan,
// allocate worst case memory for the temporary vectors // allocate worst case memory for the temporary vectors
vecChanIDsCurConChan.Init ( iMaxNumChannels ); vecChanIDsCurConChan.Init ( iMaxNumChannels );
vecvecdGains.Init ( iMaxNumChannels ); vecvecdGains.Init ( iMaxNumChannels );
vecvecdPannings.Init ( iMaxNumChannels );
vecvecsData.Init ( iMaxNumChannels ); vecvecsData.Init ( iMaxNumChannels );
vecNumAudioChannels.Init ( iMaxNumChannels ); vecNumAudioChannels.Init ( iMaxNumChannels );
vecNumFrameSizeConvBlocks.Init ( iMaxNumChannels ); vecNumFrameSizeConvBlocks.Init ( iMaxNumChannels );
@ -350,6 +351,7 @@ CServer::CServer ( const int iNewMaxNumChan,
{ {
// init vectors storing information of all channels // init vectors storing information of all channels
vecvecdGains[i].Init ( iMaxNumChannels ); vecvecdGains[i].Init ( iMaxNumChannels );
vecvecdPannings[i].Init ( iMaxNumChannels );
// we always use stereo audio buffers (see "vecsSendData") // we always use stereo audio buffers (see "vecsSendData")
vecvecsData[i].Init ( 2 /* stereo */ * DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES /* worst case buffer size */ ); vecvecsData[i].Init ( 2 /* stereo */ * DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES /* worst case buffer size */ );
@ -838,9 +840,11 @@ JitterMeas.Measure();
// "vecChanIDsCurConChan" to query the IDs of the currently // "vecChanIDsCurConChan" to query the IDs of the currently
// connected channels // connected channels
vecvecdGains[i][j] = vecChannels[iCurChanID].GetGain ( vecChanIDsCurConChan[j] ); vecvecdGains[i][j] = vecChannels[iCurChanID].GetGain ( vecChanIDsCurConChan[j] );
// consider audio fade-in // consider audio fade-in
vecvecdGains[i][j] *= vecChannels[vecChanIDsCurConChan[j]].GetFadeInGain(); vecvecdGains[i][j] *= vecChannels[vecChanIDsCurConChan[j]].GetFadeInGain();
//panning
vecvecdPannings[i][j] = vecChannels[iCurChanID].GetPan( vecChanIDsCurConChan[j] ); //((double)rand() / (double)(RAND_MAX)); //vecChannels[iCurChanID].GetGain ( vecChanIDsCurConChan[j] ); //TODO: GetPanning
} }
// If the server frame size is smaller than the received OPUS frame size, we need a conversion // If the server frame size is smaller than the received OPUS frame size, we need a conversion
@ -968,6 +972,7 @@ JitterMeas.Measure();
// actual processing of audio data -> mix // actual processing of audio data -> mix
ProcessData ( vecvecsData, ProcessData ( vecvecsData,
vecvecdGains[i], vecvecdGains[i],
vecvecdPannings[i],
vecNumAudioChannels, vecNumAudioChannels,
vecsSendData, vecsSendData,
iCurNumAudChan, iCurNumAudChan,
@ -1068,12 +1073,13 @@ opus_custom_encoder_ctl ( CurOpusEncoder,
} }
/// @brief Mix all audio data from all clients together. /// @brief Mix all audio data from all clients together.
void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData, void CServer::ProcessData (const CVector<CVector<int16_t> >& vecvecsData,
const CVector<double>& vecdGains, const CVector<double>& vecdGains,
const CVector<int>& vecNumAudioChannels, const CVector<double>& vecdPannings,
CVector<int16_t>& vecsOutData, const CVector<int>& vecNumAudioChannels,
const int iCurNumAudChan, CVector<int16_t>& vecsOutData,
const int iNumClients ) const int iCurNumAudChan,
const int iNumClients )
{ {
int i, j, k; int i, j, k;
@ -1145,6 +1151,10 @@ void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
// get a reference to the audio data and gain of the current client // get a reference to the audio data and gain of the current client
const CVector<int16_t>& vecsData = vecvecsData[j]; const CVector<int16_t>& vecsData = vecvecsData[j];
const double dGain = vecdGains[j]; const double dGain = vecdGains[j];
const double dPan = vecdPannings[j];
const double dPanCoefL = sqrt(1-dPan); // faster: (1-dPan)
const double dPanCoefR = sqrt(dPan); // (dPan)
// see http://write.flossmanuals.net/csound/b-panning-and-spatialization/ for better formula, if needed
// if channel gain is 1, avoid multiplication for speed optimization // if channel gain is 1, avoid multiplication for speed optimization
if ( dGain == static_cast<double> ( 1.0 ) ) if ( dGain == static_cast<double> ( 1.0 ) )
@ -1156,11 +1166,11 @@ void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
{ {
// left channel // left channel
vecsOutData[k] = Double2Short ( vecsOutData[k] = Double2Short (
static_cast<double> ( vecsOutData[k] ) + vecsData[i] ); static_cast<double> ( vecsOutData[k] ) + vecsData[i] * dPanCoefL);
// right channel // right channel
vecsOutData[k + 1] = Double2Short ( vecsOutData[k + 1] = Double2Short (
static_cast<double> ( vecsOutData[k + 1] ) + vecsData[i] ); static_cast<double> ( vecsOutData[k + 1] ) + vecsData[i] * dPanCoefR);
} }
} }
else else
@ -1168,8 +1178,9 @@ void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
// stereo // stereo
for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i++ ) for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i++ )
{ {
double pan = (i%2==0) ? dPanCoefL : dPanCoefR;
vecsOutData[i] = Double2Short ( vecsOutData[i] = Double2Short (
static_cast<double> ( vecsOutData[i] ) + vecsData[i] ); static_cast<double> ( vecsOutData[i] ) + vecsData[i] * pan );
} }
} }
} }
@ -1182,11 +1193,11 @@ void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
{ {
// left channel // left channel
vecsOutData[k] = Double2Short ( vecsOutData[k] = Double2Short (
vecsOutData[k] + vecsData[i] * dGain ); vecsOutData[k] + vecsData[i] * dGain * dPanCoefL);
// right channel // right channel
vecsOutData[k + 1] = Double2Short ( vecsOutData[k + 1] = Double2Short (
vecsOutData[k + 1] + vecsData[i] * dGain ); vecsOutData[k + 1] + vecsData[i] * dGain * dPanCoefR);
} }
} }
else else
@ -1194,8 +1205,10 @@ void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
// stereo // stereo
for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i++ ) for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i++ )
{ {
double pan = (i%2==0) ? dPanCoefL : dPanCoefR;
vecsOutData[i] = Double2Short ( vecsOutData[i] = Double2Short (
vecsOutData[i] + vecsData[i] * dGain ); vecsOutData[i] + vecsData[i] * dGain * pan );
} }
} }
} }

View file

@ -269,6 +269,7 @@ protected:
void ProcessData ( const CVector<CVector<int16_t> >& vecvecsData, void ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
const CVector<double>& vecdGains, const CVector<double>& vecdGains,
const CVector<double>& vecdPannings,
const CVector<int>& vecNumAudioChannels, const CVector<int>& vecNumAudioChannels,
CVector<int16_t>& vecsOutData, CVector<int16_t>& vecsOutData,
const int iCurNumAudChan, const int iCurNumAudChan,
@ -312,6 +313,7 @@ protected:
CVector<int> vecChanIDsCurConChan; CVector<int> vecChanIDsCurConChan;
CVector<CVector<double> > vecvecdGains; CVector<CVector<double> > vecvecdGains;
CVector<CVector<double> > vecvecdPannings;
CVector<CVector<int16_t> > vecvecsData; CVector<CVector<int16_t> > vecvecsData;
CVector<int> vecNumAudioChannels; CVector<int> vecNumAudioChannels;
CVector<int> vecNumFrameSizeConvBlocks; CVector<int> vecNumFrameSizeConvBlocks;

View file

@ -77,6 +77,17 @@ void CSettings::Load()
} }
} }
// stored pan values
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{
if ( GetNumericIniSet ( IniXMLDocument, "client",
QString ( "storedpanvalue%1" ).arg ( iIdx ),
0, AUD_MIX_PAN_MAX/2, iValue ) )
{
pClient->vecStoredPanValues[iIdx] = iValue;
}
}
// stored fader solo state // stored fader solo state
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ ) for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{ {
@ -455,6 +466,14 @@ void CSettings::Save()
pClient->vecStoredFaderLevels[iIdx] ); pClient->vecStoredFaderLevels[iIdx] );
} }
// stored pan values
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{
SetNumericIniSet ( IniXMLDocument, "client",
QString ( "storedpanvalue%1" ).arg ( iIdx ),
pClient->vecStoredPanValues[iIdx] );
}
// stored fader solo states // stored fader solo states
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ ) for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{ {