Server processing for channel levels
This commit is contained in:
parent
95f48eb17e
commit
a97ac9aa4e
5 changed files with 124 additions and 0 deletions
|
@ -168,6 +168,9 @@ public:
|
||||||
|
|
||||||
bool ChannelLevelsRequired() const { return bChannelLevelsRequired; }
|
bool ChannelLevelsRequired() const { return bChannelLevelsRequired; }
|
||||||
|
|
||||||
|
double GetPrevLevel() const { return dPrevLevel; }
|
||||||
|
void SetPrevLevel ( const double nPL ) { dPrevLevel = nPL; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ProtocolIsEnabled();
|
bool ProtocolIsEnabled();
|
||||||
|
|
||||||
|
@ -180,6 +183,8 @@ protected:
|
||||||
iNetwFrameSizeFact = FRAME_SIZE_FACTOR_PREFERRED;
|
iNetwFrameSizeFact = FRAME_SIZE_FACTOR_PREFERRED;
|
||||||
iNetwFrameSize = CELT_MINIMUM_NUM_BYTES;
|
iNetwFrameSize = CELT_MINIMUM_NUM_BYTES;
|
||||||
iNumAudioChannels = 1; // mono
|
iNumAudioChannels = 1; // mono
|
||||||
|
|
||||||
|
dPrevLevel = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// connection parameters
|
// connection parameters
|
||||||
|
@ -220,6 +225,7 @@ protected:
|
||||||
QMutex MutexConvBuf;
|
QMutex MutexConvBuf;
|
||||||
|
|
||||||
bool bChannelLevelsRequired;
|
bool bChannelLevelsRequired;
|
||||||
|
double dPrevLevel;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnSendProtMessage ( CVector<uint8_t> vecMessage );
|
void OnSendProtMessage ( CVector<uint8_t> vecMessage );
|
||||||
|
|
|
@ -199,6 +199,9 @@ LED bar: lbr
|
||||||
// list
|
// list
|
||||||
#define PING_UPDATE_TIME_SERVER_LIST_MS 2000 // ms
|
#define PING_UPDATE_TIME_SERVER_LIST_MS 2000 // ms
|
||||||
|
|
||||||
|
// defines the interval between Channel Level updates from the server
|
||||||
|
#define CHANNEL_LEVEL_UPDATE_INTERVAL 100 // number of frames
|
||||||
|
|
||||||
// time-out until a registered server is deleted from the server list if no
|
// time-out until a registered server is deleted from the server list if no
|
||||||
// new registering was made in minutes
|
// new registering was made in minutes
|
||||||
#define SERVLIST_TIME_OUT_MINUTES 60 // minutes
|
#define SERVLIST_TIME_OUT_MINUTES 60 // minutes
|
||||||
|
|
|
@ -2039,6 +2039,11 @@ bool CProtocol::EvaluateCLChannelLevelListMes ( const CHostAddress& InetAdd
|
||||||
// may have one too many entries, last being 0xF
|
// may have one too many entries, last being 0xF
|
||||||
int iVecLen = iDataLen * 2; // one ushort per channel
|
int iVecLen = iDataLen * 2; // one ushort per channel
|
||||||
|
|
||||||
|
if ( iVecLen > MAX_NUM_CHANNELS )
|
||||||
|
{
|
||||||
|
return true; // return error code
|
||||||
|
}
|
||||||
|
|
||||||
CVector<uint16_t> vecLevelList ( iVecLen );
|
CVector<uint16_t> vecLevelList ( iVecLen );
|
||||||
|
|
||||||
for (int i = 0, j = 0; i < iDataLen; i++, j += 2 )
|
for (int i = 0, j = 0; i < iDataLen; i++, j += 2 )
|
||||||
|
|
|
@ -335,6 +335,8 @@ CServer::CServer ( const int iNewMaxNumChan,
|
||||||
// allocate worst case memory for the coded data
|
// allocate worst case memory for the coded data
|
||||||
vecbyCodedData.Init ( MAX_SIZE_BYTES_NETW_BUF );
|
vecbyCodedData.Init ( MAX_SIZE_BYTES_NETW_BUF );
|
||||||
|
|
||||||
|
// allocate worst case memory for the channel levels
|
||||||
|
vecChannelLevels.Init ( iMaxNumChannels );
|
||||||
|
|
||||||
// enable history graph (if requested)
|
// enable history graph (if requested)
|
||||||
if ( !strHistoryFileName.isEmpty() )
|
if ( !strHistoryFileName.isEmpty() )
|
||||||
|
@ -864,6 +866,7 @@ JitterMeas.Measure();
|
||||||
// some inits
|
// some inits
|
||||||
int iNumClients = 0; // init connected client counter
|
int iNumClients = 0; // init connected client counter
|
||||||
bool bChannelIsNowDisconnected = false;
|
bool bChannelIsNowDisconnected = false;
|
||||||
|
bool bSendChannelLevels = false;
|
||||||
|
|
||||||
// Make put and get calls thread safe. Do not forget to unlock mutex
|
// Make put and get calls thread safe. Do not forget to unlock mutex
|
||||||
// afterwards!
|
// afterwards!
|
||||||
|
@ -1007,6 +1010,29 @@ JitterMeas.Measure();
|
||||||
// one client is connected.
|
// one client is connected.
|
||||||
if ( iNumClients > 0 )
|
if ( iNumClients > 0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Low frequency updates
|
||||||
|
if ( iFrameCount > CHANNEL_LEVEL_UPDATE_INTERVAL )
|
||||||
|
{
|
||||||
|
iFrameCount = 0;
|
||||||
|
|
||||||
|
// Calculate channel levels if any client has requested them
|
||||||
|
for ( int i = 0; i < iNumClients; i++ )
|
||||||
|
{
|
||||||
|
if ( vecChannels[ vecChanIDsCurConChan[i] ].ChannelLevelsRequired() )
|
||||||
|
{
|
||||||
|
bSendChannelLevels = true;
|
||||||
|
|
||||||
|
CreateLevelsForAllConChannels ( iNumClients,
|
||||||
|
vecNumAudioChannels,
|
||||||
|
vecvecsData,
|
||||||
|
vecChannelLevels );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iFrameCount++;
|
||||||
|
|
||||||
for ( int i = 0; i < iNumClients; i++ )
|
for ( int i = 0; i < iNumClients; i++ )
|
||||||
{
|
{
|
||||||
// get actual ID of current channel
|
// get actual ID of current channel
|
||||||
|
@ -1095,6 +1121,12 @@ opus_custom_encoder_ctl ( CurOpusEncoder,
|
||||||
|
|
||||||
// update socket buffer size
|
// update socket buffer size
|
||||||
vecChannels[iCurChanID].UpdateSocketBufferSize();
|
vecChannels[iCurChanID].UpdateSocketBufferSize();
|
||||||
|
|
||||||
|
// send channel levels
|
||||||
|
if ( bSendChannelLevels && vecChannels[iCurChanID].ChannelLevelsRequired() )
|
||||||
|
{
|
||||||
|
ConnLessProtocol.CreateCLChannelLevelListMes ( vecChannels[iCurChanID].GetAddress(), vecChannelLevels, iNumClients );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1574,3 +1606,69 @@ void CServer::customEvent ( QEvent* pEvent )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Compute frame peak level for each client
|
||||||
|
void CServer::CreateLevelsForAllConChannels ( const int iNumClients,
|
||||||
|
const CVector<int>& vecNumAudioChannels,
|
||||||
|
const CVector<CVector<int16_t> > vecvecsData,
|
||||||
|
CVector<uint16_t>& vecLevelsOut )
|
||||||
|
{
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
// init return vector with zeros since we mix all channels on that vector
|
||||||
|
vecLevelsOut.Reset ( 0 );
|
||||||
|
|
||||||
|
for ( j = 0; j < iNumClients; j++ )
|
||||||
|
{
|
||||||
|
// get a reference to the audio data
|
||||||
|
const CVector<int16_t>& vecsData = vecvecsData[j];
|
||||||
|
|
||||||
|
double dCurLevel = 0.0;
|
||||||
|
if ( vecNumAudioChannels[j] == 1 )
|
||||||
|
{
|
||||||
|
// mono
|
||||||
|
for ( i = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i += 3 )
|
||||||
|
{
|
||||||
|
dCurLevel = std::max ( dCurLevel, std::abs ( static_cast<double> ( vecsData[i] ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo: apply stereo-to-mono attenuation
|
||||||
|
for ( i = 0, k = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i += 3, k += 6 )
|
||||||
|
{
|
||||||
|
double sMix = ( static_cast<double> ( vecsData[k] ) + vecsData[k + 1] ) / 2;
|
||||||
|
dCurLevel = std::max ( dCurLevel, std::abs ( sMix ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// smoothing
|
||||||
|
int iChId = vecChanIDsCurConChan [ j ];
|
||||||
|
dCurLevel = std::max ( dCurLevel, vecChannels[ iChId ].GetPrevLevel() * 0.5 );
|
||||||
|
vecChannels[ iChId ].SetPrevLevel ( dCurLevel );
|
||||||
|
|
||||||
|
// logarithmic measure
|
||||||
|
const double dNormChanLevel = dCurLevel / _MAXSHORT;
|
||||||
|
double dCurSigLevel;
|
||||||
|
if ( dNormChanLevel > 0 )
|
||||||
|
{
|
||||||
|
dCurSigLevel = 20.0 * log10 ( dNormChanLevel );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dCurSigLevel = -100000.0; // large negative value
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to signal level meter
|
||||||
|
dCurSigLevel -= LOW_BOUND_SIG_METER;
|
||||||
|
dCurSigLevel *= NUM_STEPS_LED_BAR /
|
||||||
|
( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER );
|
||||||
|
|
||||||
|
if ( dCurSigLevel < 0 )
|
||||||
|
{
|
||||||
|
dCurSigLevel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vecLevelsOut[j] = static_cast<uint16_t> ( ceil ( dCurSigLevel ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
12
src/server.h
12
src/server.h
|
@ -28,6 +28,7 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
#include <algorithm>
|
||||||
#ifdef USE_OPUS_SHARED_LIB
|
#ifdef USE_OPUS_SHARED_LIB
|
||||||
# include "opus/opus_custom.h"
|
# include "opus/opus_custom.h"
|
||||||
#else
|
#else
|
||||||
|
@ -225,6 +226,11 @@ protected:
|
||||||
// if server mode is normal or double system frame size
|
// if server mode is normal or double system frame size
|
||||||
bool bUseDoubleSystemFrameSize;
|
bool bUseDoubleSystemFrameSize;
|
||||||
|
|
||||||
|
void CreateLevelsForAllConChannels ( const int iNumClients,
|
||||||
|
const CVector<int>& vecNumAudioChannels,
|
||||||
|
const CVector<CVector<int16_t> > vecvecsData,
|
||||||
|
CVector<uint16_t>& vecLevelsOut );
|
||||||
|
|
||||||
// do not use the vector class since CChannel does not have appropriate
|
// do not use the vector class since CChannel does not have appropriate
|
||||||
// copy constructor/operator
|
// copy constructor/operator
|
||||||
CChannel vecChannels[MAX_NUM_CHANNELS];
|
CChannel vecChannels[MAX_NUM_CHANNELS];
|
||||||
|
@ -255,12 +261,18 @@ protected:
|
||||||
CVector<int16_t> vecsSendData;
|
CVector<int16_t> vecsSendData;
|
||||||
CVector<uint8_t> vecbyCodedData;
|
CVector<uint8_t> vecbyCodedData;
|
||||||
|
|
||||||
|
// Channel levels
|
||||||
|
CVector<uint16_t> vecChannelLevels;
|
||||||
|
|
||||||
// actual working objects
|
// actual working objects
|
||||||
CHighPrioSocket Socket;
|
CHighPrioSocket Socket;
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
CServerLogging Logging;
|
CServerLogging Logging;
|
||||||
|
|
||||||
|
// channel level update frame interval counter
|
||||||
|
uint16_t iFrameCount;
|
||||||
|
|
||||||
// recording thread
|
// recording thread
|
||||||
recorder::CJamRecorder JamRecorder;
|
recorder::CJamRecorder JamRecorder;
|
||||||
bool bEnableRecording;
|
bool bEnableRecording;
|
||||||
|
|
Loading…
Reference in a new issue