Skip to content

Commit bd3b609

Browse files
authored
Merge pull request #3429 from softins/rate-limit-pan
Apply rate limiting to Pan as well as Gain
2 parents 7b86fea + e4c23b5 commit bd3b609

File tree

2 files changed

+73
-41
lines changed

2 files changed

+73
-41
lines changed

src/client.cpp

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,9 @@ CClient::CClient ( const quint16 iPortNumber,
176176
PreciseTime.start();
177177

178178
// set gain delay timer to single-shot and connect handler function
179-
TimerGain.setSingleShot ( true );
179+
TimerGainOrPan.setSingleShot ( true );
180180

181-
QObject::connect ( &TimerGain, &QTimer::timeout, this, &CClient::OnTimerRemoteChanGain );
181+
QObject::connect ( &TimerGainOrPan, &QTimer::timeout, this, &CClient::OnTimerRemoteChanGainOrPan );
182182

183183
// start the socket (it is important to start the socket after all
184184
// initializations and connections)
@@ -431,27 +431,28 @@ void CClient::SetDoAutoSockBufSize ( const bool bValue )
431431
CreateServerJitterBufferMessage();
432432
}
433433

434-
// In order not to flood the server with gain change messages, particularly when using
434+
// In order not to flood the server with gain or pan change messages, particularly when using
435435
// a MIDI controller, a timer is used to limit the rate at which such messages are generated.
436436
// This avoids a potential long backlog of messages, since each must be ACKed before the next
437437
// can be sent, and this ACK is subject to the latency of the server connection.
438438
//
439-
// When the first gain change message is requested after an idle period (i.e. the timer is not
440-
// running), it will be sent immediately, and a 300ms timer started.
439+
// When the first gain or pan change message is requested after an idle period (i.e. the timer is not
440+
// running), it will be sent immediately, and a timer started. The timer period is dependent on
441+
// the current ping time to the remote server.
441442
//
442-
// If a gain change message is requested while the timer is still running, the new gain is not sent,
443-
// but just stored in clientChannels[iId].newGain, and the minGainId and maxGainId updated to note
444-
// the range of IDs that must be checked when the time expires (this will usually be a single channel
445-
// unless channel grouping is being used). This avoids having to check all possible channels.
443+
// If a gain or pan change message is requested while the timer is still running, the new value is not sent,
444+
// but just stored in newGain or newPan within clientChannels[iId], and the minGainOrPanId and maxGainOrPanId
445+
// updated to note the range of IDs that must be checked when the time expires (this will usually be a single
446+
// channel unless channel grouping is being used). This avoids having to check all possible channels.
446447
//
447-
// When the timer fires, the channels minGainId <= iId < maxGainId are checked by comparing the last sent value
448-
// in clientChannels[iId].oldGain with any pending value in clientChannels[iId].newGain, and if they differ,
449-
// the new value is sent, updating clientChannels[iId].oldGain with the sent value. If any new values are
450-
// sent, the timer is restarted so that further immediate updates will be pended.
448+
// When the timer fires, the channels minGainOrPanId <= iId < maxGainOrPanId are checked by comparing the
449+
// last sent values in oldGain or oldPan with any pending values in newGain or newPan, and if they differ,
450+
// the new value is sent, updating oldGain or oldPan with the sent value. If any new values are sent,
451+
// the timer is restarted so that further immediate updates will be pended.
451452

452453
void CClient::SetRemoteChanGain ( const int iId, const float fGain, const bool bIsMyOwnFader )
453454
{
454-
QMutexLocker locker ( &MutexGain );
455+
QMutexLocker locker ( &MutexGainOrPan );
455456

456457
CClientChannel* clientChan = &clientChannels[iId];
457458

@@ -461,17 +462,17 @@ void CClient::SetRemoteChanGain ( const int iId, const float fGain, const bool b
461462
fMuteOutStreamGain = fGain;
462463
}
463464

464-
if ( TimerGain.isActive() )
465+
if ( TimerGainOrPan.isActive() )
465466
{
466467
// just update the new value for sending later;
467468
// will compare with oldGain when the timer fires
468469
clientChan->newGain = fGain;
469470

470471
// update range of channel IDs to check in the timer
471-
if ( iId < minGainId )
472-
minGainId = iId; // first value to check
473-
if ( iId >= maxGainId )
474-
maxGainId = iId + 1; // first value NOT to check
472+
if ( iId < minGainOrPanId )
473+
minGainOrPanId = iId; // first value to check
474+
if ( iId >= maxGainOrPanId )
475+
maxGainOrPanId = iId + 1; // first value NOT to check
475476

476477
return;
477478
}
@@ -481,15 +482,15 @@ void CClient::SetRemoteChanGain ( const int iId, const float fGain, const bool b
481482
clientChan->oldGain = clientChan->newGain = fGain;
482483
Channel.SetRemoteChanGain ( clientChan->iServerChannelID, fGain ); // translate client channel to server channel ID
483484

484-
StartDelayTimer();
485+
StartTimerGainOrPan();
485486
}
486487

487-
void CClient::OnTimerRemoteChanGain()
488+
void CClient::OnTimerRemoteChanGainOrPan()
488489
{
489-
QMutexLocker locker ( &MutexGain );
490+
QMutexLocker locker ( &MutexGainOrPan );
490491
bool bSent = false;
491492

492-
for ( int iId = minGainId; iId < maxGainId; iId++ )
493+
for ( int iId = minGainOrPanId; iId < maxGainOrPanId; iId++ )
493494
{
494495
CClientChannel* clientChan = &clientChannels[iId];
495496

@@ -500,37 +501,69 @@ void CClient::OnTimerRemoteChanGain()
500501
Channel.SetRemoteChanGain ( clientChan->iServerChannelID, fGain ); // translate client channel to server channel ID
501502
bSent = true;
502503
}
504+
505+
if ( clientChan->newPan != clientChan->oldPan )
506+
{
507+
// send new pan and record as old pan
508+
float fPan = clientChan->oldPan = clientChan->newPan;
509+
Channel.SetRemoteChanPan ( clientChan->iServerChannelID, fPan ); // translate client channel to server channel ID
510+
bSent = true;
511+
}
503512
}
504513

505-
// if a new gain has been sent, reset the range of channel IDs to empty and start timer
514+
// if a new gain or pan has been sent, reset the range of channel IDs to empty and start timer
506515
if ( bSent )
507516
{
508-
StartDelayTimer();
517+
StartTimerGainOrPan();
509518
}
510519
}
511520

512521
// reset the range of channel IDs to check and start the delay timer
513-
void CClient::StartDelayTimer()
522+
void CClient::StartTimerGainOrPan()
514523
{
515-
maxGainId = 0;
516-
minGainId = MAX_NUM_CHANNELS;
524+
maxGainOrPanId = 0;
525+
minGainOrPanId = MAX_NUM_CHANNELS;
517526

518527
// start timer to delay sending further updates
519528
// use longer delay when connected to server with higher ping time,
520529
// double the ping time in order to allow a bit of overhead for other messages
521530
if ( iCurPingTime < DEFAULT_GAIN_DELAY_PERIOD_MS / 2 )
522531
{
523-
TimerGain.start ( DEFAULT_GAIN_DELAY_PERIOD_MS );
532+
TimerGainOrPan.start ( DEFAULT_GAIN_DELAY_PERIOD_MS );
524533
}
525534
else
526535
{
527-
TimerGain.start ( iCurPingTime * 2 );
536+
TimerGainOrPan.start ( iCurPingTime * 2 );
528537
}
529538
}
530539

531540
void CClient::SetRemoteChanPan ( const int iId, const float fPan )
532541
{
533-
Channel.SetRemoteChanPan ( clientChannels[iId].iServerChannelID, fPan ); // translate client channel to server channel ID
542+
QMutexLocker locker ( &MutexGainOrPan );
543+
544+
CClientChannel* clientChan = &clientChannels[iId];
545+
546+
if ( TimerGainOrPan.isActive() )
547+
{
548+
// just update the new value for sending later;
549+
// will compare with oldPan when the timer fires
550+
clientChan->newPan = fPan;
551+
552+
// update range of channel IDs to check in the timer
553+
if ( iId < minGainOrPanId )
554+
minGainOrPanId = iId; // first value to check
555+
if ( iId >= maxGainOrPanId )
556+
maxGainOrPanId = iId + 1; // first value NOT to check
557+
558+
return;
559+
}
560+
561+
// here the timer was not active:
562+
// send the actual gain and reset the range of channel IDs to empty
563+
clientChan->oldPan = clientChan->newPan = fPan;
564+
Channel.SetRemoteChanPan ( clientChan->iServerChannelID, fPan ); // translate client channel to server channel ID
565+
566+
StartTimerGainOrPan();
534567
}
535568

536569
bool CClient::SetServerAddr ( QString strNAddr )
@@ -1541,6 +1574,7 @@ int CClient::FindClientChannel ( const int iServerChannelID, const bool bCreateI
15411574
clientChan->iJoinSequence = ++iJoinSequence;
15421575

15431576
clientChan->oldGain = clientChan->newGain = 1.0f;
1577+
clientChan->oldPan = clientChan->newPan = 0.5f;
15441578

15451579
clientChan->level = 0;
15461580

src/client.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class CClientChannel
112112
int iJoinSequence; // order of joining of session participants
113113

114114
float oldGain, newGain; // for rate-limiting sending of gain messages
115+
float oldPan, newPan; // for rate-limiting sending of pan messages
115116

116117
uint16_t level; // last value of level meter received for channel
117118

@@ -255,10 +256,9 @@ class CClient : public QObject
255256
void SetMuteOutStream ( const bool bDoMute ) { bMuteOutStream = bDoMute; }
256257

257258
void SetRemoteChanGain ( const int iId, const float fGain, const bool bIsMyOwnFader );
258-
void OnTimerRemoteChanGain();
259-
void StartDelayTimer();
260-
261259
void SetRemoteChanPan ( const int iId, const float fPan );
260+
void OnTimerRemoteChanGainOrPan();
261+
void StartTimerGainOrPan();
262262

263263
void SetInputBoost ( const int iNewBoost ) { iInputBoost = iNewBoost; }
264264

@@ -393,13 +393,11 @@ class CClient : public QObject
393393
// for ping measurement
394394
QElapsedTimer PreciseTime;
395395

396-
// for gain rate limiting
397-
QMutex MutexGain;
398-
QTimer TimerGain;
399-
int minGainId;
400-
int maxGainId;
401-
float oldGain[MAX_NUM_CHANNELS];
402-
float newGain[MAX_NUM_CHANNELS];
396+
// for gain or pan rate limiting
397+
QMutex MutexGainOrPan;
398+
QTimer TimerGainOrPan;
399+
int minGainOrPanId;
400+
int maxGainOrPanId;
403401
int iCurPingTime;
404402

405403
CSignalHandler* pSignalHandler;

0 commit comments

Comments
 (0)