From 9fbe334d8abf16bc89a79b6f6259bb1d789e481e Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Sat, 11 Jun 2011 18:18:46 +0000 Subject: [PATCH] memory optimization --- src/util.h | 1724 ++++++++++++++++++++++++++-------------------------- 1 file changed, 862 insertions(+), 862 deletions(-) diff --git a/src/util.h b/src/util.h index f2651508..518b3138 100755 --- a/src/util.h +++ b/src/util.h @@ -1,862 +1,862 @@ -/******************************************************************************\ - * Copyright (c) 2004-2011 - * - * Author(s): - * Volker Fischer - * - ****************************************************************************** - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -\******************************************************************************/ - -#if !defined ( UTIL_HOIH934256GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) -#define UTIL_HOIH934256GEKJH98_3_43445KJIUHF1912__INCLUDED_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "global.h" -using namespace std; // because of the library: "vector" -#ifdef _WIN32 -# include "../windows/moc/aboutdlgbase.h" -# include -# include -#else -# ifdef _IS_QMAKE_CONFIG -# include "ui_aboutdlgbase.h" -# else -# include "moc/aboutdlgbase.h" -# endif -#endif - - -/* Definitions ****************************************************************/ -#define METER_FLY_BACK 2 - - -/* Global functions ***********************************************************/ -// converting double to short -inline short Double2Short ( const double dInput ) -{ - // lower bound - if ( dInput < _MINSHORT ) - { - return _MINSHORT; - } - - // upper bound - if ( dInput > _MAXSHORT ) - { - return _MAXSHORT; - } - - return (short) dInput; -} - -// debug error handling -void DebugError ( const QString& pchErDescr, - const QString& pchPar1Descr, - const double dPar1, - const QString& pchPar2Descr, - const double dPar2 ); - - -/******************************************************************************\ -* CVector Base Class * -\******************************************************************************/ -template class CVector : public std::vector -{ -public: - CVector() : iVectorSize ( 0 ) { pData = this->begin(); } - CVector ( const int iNeSi ) { Init(iNeSi); } - CVector ( const int iNeSi, const TData tInVa ) { Init ( iNeSi, tInVa ); } - - // Copy constructor: The order of the initialization list must not be - // changed. First, the base class must be initialized, then the pData - // pointer must be set to the new data source. The bit access is, by - // default, reset. - CVector ( const CVector& vecI ) : - std::vector ( static_cast&> ( vecI ) ), - iVectorSize ( vecI.Size() ) { pData = this->begin(); } - - void Init ( const int iNewSize ); - - // use this init to give all elements a defined value - void Init ( const int iNewSize, const TData tIniVal ); - void Reset ( const TData tResetVal ); - - void Enlarge ( const int iAddedSize ); - void Add ( const TData& tI ) { Enlarge ( 1 ); pData[iVectorSize - 1] = tI; } - - inline int Size() const { return iVectorSize; } - - // This operator allows for a l-value assignment of this object: - // CVector[x] = y is possible - inline TData& operator[] ( const int iPos ) { -#ifdef _DEBUG_ - if ( ( iPos < 0 ) || ( iPos > iVectorSize - 1 ) ) - { - DebugError ( "Writing vector out of bounds", "Vector size", - iVectorSize, "New parameter", iPos ); - } -#endif - return pData[iPos]; } - - inline TData operator[] ( const int iPos ) const { -#ifdef _DEBUG_ - if ( ( iPos < 0 ) || ( iPos > iVectorSize - 1 ) ) - { - DebugError ( "Reading vector out of bounds", "Vector size", - iVectorSize, "New parameter", iPos ); - } -#endif - return pData[iPos]; } - - inline CVector& operator= ( const CVector& vecI ) { -#ifdef _DEBUG_ - // Vectors which shall be copied MUST have same size! (If this is - // satisfied, the parameter "iVectorSize" must not be adjusted as - // a side effect) - if ( vecI.Size() != iVectorSize ) - { - DebugError ( "Vector operator=() different size", "Vector size", - iVectorSize, "New parameter", vecI.Size() ); - } -#endif - vector::operator= ( vecI ); - - // reset my data pointer in case, the operator=() of the base class - // did change the actual memory - pData = this->begin(); - - return *this; - } - -protected: - typename std::vector::iterator pData; - int iVectorSize; -}; - - -/* Implementation *************************************************************/ -template void CVector::Init ( const int iNewSize ) -{ - iVectorSize = iNewSize; - - // clear old buffer and reserve memory for new buffer, get iterator - // for pointer operations - this->clear(); - this->resize ( iNewSize ); - pData = this->begin(); -} - -template void CVector::Init ( const int iNewSize, - const TData tIniVal ) -{ - // call actual init routine - Init ( iNewSize ); - - // set values - Reset ( tIniVal ); -} - -template void CVector::Enlarge ( const int iAddedSize ) -{ - iVectorSize += iAddedSize; - this->resize ( iVectorSize ); - - // we have to reset the pointer since it could be that the vector size was - // zero before enlarging the vector - pData = this->begin(); -} - -template void CVector::Reset ( const TData tResetVal ) -{ - // set all values to reset value - for ( int i = 0; i < iVectorSize; i++ ) - { - pData[i] = tResetVal; - } -} - - -/******************************************************************************\ -* CFIFO Class (First In, First Out) * -\******************************************************************************/ -template class CFIFO : public CVector -{ -public: - CFIFO() : CVector(), iCurIdx ( 0 ) {} - CFIFO ( const int iNeSi ) : CVector(iNeSi), iCurIdx ( 0 ) {} - CFIFO ( const int iNeSi, const TData tInVa ) : - CVector ( iNeSi, tInVa ), iCurIdx ( 0 ) {} - - void Add ( const TData tNewD ); - inline TData Get() { return this->pData[iCurIdx]; } - - virtual void Init ( const int iNewSize ); - virtual void Init ( const int iNewSize, const TData tIniVal ); - -protected: - int iCurIdx; -}; - -template void CFIFO::Init ( const int iNewSize ) -{ - iCurIdx = 0; - CVector::Init ( iNewSize ); -} - -template void CFIFO::Init ( const int iNewSize, - const TData tIniVal ) -{ - iCurIdx = 0; - CVector::Init ( iNewSize, tIniVal ); -} - -template void CFIFO::Add ( const TData tNewD ) -{ - this->pData[iCurIdx] = tNewD; - - // increment index - iCurIdx++; - if ( iCurIdx >= this->iVectorSize ) - { - iCurIdx = 0; - } -} - - -/******************************************************************************\ -* CMovingAv Class (Moving Average) * -\******************************************************************************/ -template class CMovingAv : public CVector -{ -public: - CMovingAv() : - CVector(), - iCurIdx ( 0 ), - iNorm ( 0 ), - tCurAvResult ( TData ( 0 ) ), - tNoDataResult ( TData ( 0 ) ) {} - - void Add ( const TData tNewD ); - - void Init ( const int iNewSize, - const TData tNNoDRes = TData ( 0 ) ); - - void Reset(); - - inline TData GetAverage() - { - if ( this->iNorm == 0 ) - { - return tNoDataResult; - } - else - { - return tCurAvResult / this->iNorm; - } - } - - bool IsInitialized() { return ( this->iNorm == this->iVectorSize ); } - -protected: - int iCurIdx; - int iNorm; - TData tCurAvResult; - TData tNoDataResult; -}; - -template void CMovingAv::Init ( const int iNewSize, - const TData tNNoDRes ) -{ - iNorm = 0; - iCurIdx = 0; - tCurAvResult = TData ( 0 ); // only for scalars! - tNoDataResult = tNNoDRes; - CVector::Init ( iNewSize ); -} - -template void CMovingAv::Reset() -{ - iNorm = 0; - iCurIdx = 0; - tCurAvResult = TData ( 0 ); // only for scalars! - CVector::Reset ( TData ( 0 ) ); -} - -template void CMovingAv::Add ( const TData tNewD ) -{ -/* - Optimized calculation of the moving average. We only add a new value and - subtract the old value from the result. We only need one addition and a - history buffer. -*/ - // subtract oldest value - tCurAvResult -= this->pData[iCurIdx]; - - // add new value and write in memory - tCurAvResult += tNewD; - this->pData[iCurIdx] = tNewD; - - // increase position pointer and test if wrap - iCurIdx++; - if ( iCurIdx >= this->iVectorSize ) - { - iCurIdx = 0; - } - - // take care of norm - if ( this->iNorm < this->iVectorSize ) - { - this->iNorm++; - } -} - - -/******************************************************************************\ -* GUI Utilities * -\******************************************************************************/ -// About dialog ---------------------------------------------------------------- -class CAboutDlg : public QDialog, private Ui_CAboutDlgBase -{ - Q_OBJECT - -public: - CAboutDlg ( QWidget* parent = 0 ); - - static QString GetVersionAndNameStr ( const bool bWithHtml = true ); -}; - - -// Help menu ------------------------------------------------------------------- -class CLlconHelpMenu : public QMenu -{ - Q_OBJECT - -public: - CLlconHelpMenu ( QWidget* parent = 0 ); - -protected: - CAboutDlg AboutDlg; - -public slots: - void OnHelpWhatsThis() { QWhatsThis::enterWhatsThisMode(); } - void OnHelpAbout() { AboutDlg.exec(); } - void OnHelpDownloadLink() - { QDesktopServices::openUrl ( QUrl ( LLCON_DOWNLOAD_URL ) ); } -}; - - -/******************************************************************************\ -* Other Classes * -\******************************************************************************/ -// Stereo signal level meter --------------------------------------------------- -class CStereoSignalLevelMeter -{ -public: - CStereoSignalLevelMeter() { Reset(); } - - void Update ( CVector& vecsAudio ); - double MicLevelLeft() { return CalcLogResult ( dCurLevelL ); } - double MicLevelRight() { return CalcLogResult ( dCurLevelR ); } - void Reset() { dCurLevelL = 0.0; dCurLevelR = 0.0; } - -protected: - double CalcLogResult ( const double& dLinearLevel ); - double UpdateCurLevel ( double dCurLevel, const short& sMax ); - - double dCurLevelL; - double dCurLevelR; -}; - - -// Host address ---------------------------------------------------------------- -class CHostAddress -{ -public: - enum EStringMode - { - SM_IP_PORT, - SM_IP_NO_LAST_BYTE, - SM_IP_NO_LAST_BYTE_PORT - }; - - CHostAddress() : - InetAddr ( static_cast ( 0 ) ), - iPort ( 0 ) {} - - CHostAddress ( const QHostAddress NInetAddr, - const quint16 iNPort ) : - InetAddr ( NInetAddr ), - iPort ( iNPort ) {} - - CHostAddress ( const CHostAddress& NHAddr ) : - InetAddr ( NHAddr.InetAddr ), - iPort ( NHAddr.iPort ) {} - - // copy operator - CHostAddress& operator= ( const CHostAddress& NHAddr ) - { - InetAddr = NHAddr.InetAddr; - iPort = NHAddr.iPort; - return *this; - } - - // compare operator - bool operator== ( const CHostAddress& CompAddr ) // compare operator - { - return ( ( CompAddr.InetAddr == InetAddr ) && - ( CompAddr.iPort == iPort ) ); - } - - QString toString ( const EStringMode eStringMode = SM_IP_PORT ) const - { - QString strReturn = InetAddr.toString(); - - // special case: for local host address, we do not replace the last byte - if ( ( ( eStringMode == SM_IP_NO_LAST_BYTE ) || - ( eStringMode == SM_IP_NO_LAST_BYTE_PORT ) ) && - ( InetAddr != QHostAddress ( QHostAddress::LocalHost ) ) ) - { - // replace last byte by an "x" - strReturn = strReturn.section ( ".", 0, 2 ) + ".x"; - } - - if ( ( eStringMode == SM_IP_PORT ) || - ( eStringMode == SM_IP_NO_LAST_BYTE_PORT ) ) - { - // add port number after a semicolon - strReturn += ":" + QString().setNum ( iPort ); - } - - return strReturn; - } - - QHostAddress InetAddr; - quint16 iPort; -}; - - -// Short info of a channel ----------------------------------------------------- -class CChannelShortInfo -{ -public: - CChannelShortInfo() : - iChanID ( 0 ), - iIpAddr ( 0 ), - strName ( "" ) {} - - CChannelShortInfo ( const int iNID, - const quint32 nIP, - const QString nN ) : - iChanID ( iNID ), - iIpAddr ( nIP ), - strName ( nN ) {} - - int iChanID; - quint32 iIpAddr; - QString strName; -}; - - -// Server info ----------------------------------------------------------------- -class CServerCoreInfo -{ -public: - CServerCoreInfo() : - iLocalPortNumber ( 0 ), - strName ( "" ), - strTopic ( "" ), - eCountry ( QLocale::AnyCountry ), - strCity ( "" ), - iMaxNumClients ( 0 ), - bPermanentOnline ( false ) {} - - CServerCoreInfo ( - const quint16 NLocPort, - const QString& NsName, - const QString& NsTopic, - const QLocale::Country& NeCountry, - const QString& NsCity, - const int NiMaxNumClients, - const bool NbPermOnline) : - iLocalPortNumber ( NLocPort ), - strName ( NsName ), - strTopic ( NsTopic ), - eCountry ( NeCountry ), - strCity ( NsCity ), - iMaxNumClients ( NiMaxNumClients ), - bPermanentOnline ( NbPermOnline ) {} - -public: - // local port number of the server - quint16 iLocalPortNumber; - - // name of the server - QString strName; - - // topic of the current jam session or server - QString strTopic; - - // country in which the server is located - QLocale::Country eCountry; - - // city in which the server is located - QString strCity; - - // maximum number of clients which can connect to the server at the same - // time - int iMaxNumClients; - - // is the server permanently online or not (flag) - bool bPermanentOnline; -}; - -class CServerInfo : public CServerCoreInfo -{ -public: - CServerInfo() : - CServerCoreInfo ( 0, - "", - "", - QLocale::AnyCountry, - "", - 0, - false ), HostAddr ( CHostAddress() ) {} - - CServerInfo ( - const CHostAddress& NHAddr, - const quint16 NLocPort, - const QString& NsName, - const QString& NsTopic, - const QLocale::Country& NeCountry, - const QString& NsCity, - const int NiMaxNumClients, - const bool NbPermOnline) : - CServerCoreInfo ( NLocPort, - NsName, - NsTopic, - NeCountry, - NsCity, - NiMaxNumClients, - NbPermOnline ), HostAddr ( NHAddr ) {} - -public: - // internet address of the server - CHostAddress HostAddr; -}; - - -// Audio compression type enum ------------------------------------------------- -enum EAudComprType -{ - CT_NONE = 0, - CT_CELT = 1 -}; - - -// Get data status enum -------------------------------------------------------- -enum EGetDataStat -{ - GS_BUFFER_OK, - GS_BUFFER_UNDERRUN, - GS_CHAN_NOW_DISCONNECTED, - GS_CHAN_NOT_CONNECTED -}; - - -// GUI design enum ------------------------------------------------------------- -enum EGUIDesign -{ - GD_STANDARD = 0, - GD_ORIGINAL = 1 -}; - - -// Network transport properties ------------------------------------------------ -class CNetworkTransportProps -{ -public: - CNetworkTransportProps() : - iBaseNetworkPacketSize ( 0 ), - iBlockSizeFact ( 0 ), - iNumAudioChannels ( 0 ), - iSampleRate ( 0 ), - eAudioCodingType ( CT_NONE ), - iAudioCodingArg ( 0 ) {} - - CNetworkTransportProps ( const uint32_t iNBNPS, - const uint16_t iNBSF, - const uint32_t iNNACH, - const uint32_t iNSR, - const EAudComprType eNACT, - const uint32_t iNVers, - const int32_t iNACA ) : - iBaseNetworkPacketSize ( iNBNPS ), - iBlockSizeFact ( iNBSF ), - iNumAudioChannels ( iNNACH ), - iSampleRate ( iNSR ), - eAudioCodingType ( eNACT ), - iVersion ( iNVers ), - iAudioCodingArg ( iNACA ) {} - - uint32_t iBaseNetworkPacketSize; - uint16_t iBlockSizeFact; - uint32_t iNumAudioChannels; - uint32_t iSampleRate; - EAudComprType eAudioCodingType; - uint32_t iVersion; - int32_t iAudioCodingArg; -}; - - -// Network utility functions --------------------------------------------------- -class LlconNetwUtil -{ -public: - static bool ParseNetworkAddress ( QString strAddress, - CHostAddress& HostAddress ); -}; - - -// Audio reverbration ---------------------------------------------------------- -class CAudioReverb -{ -public: - CAudioReverb() {} - - void Init ( const int iSampleRate, const double rT60 = (double) 5.0 ); - void Clear(); - double ProcessSample ( const double input ); - -protected: - void setT60 ( const double rT60, const int iSampleRate ); - bool isPrime ( const int number ); - - CFIFO allpassDelays_[3]; - CFIFO combDelays_[4]; - double allpassCoefficient_; - double combCoefficient_[4]; -}; - - -// CRC ------------------------------------------------------------------------- -class CCRC -{ -public: - CCRC() : iPoly ( ( 1 << 5 ) | ( 1 << 12 ) ), iBitOutMask ( 1 << 16 ) - { Reset(); } - - void Reset(); - void AddByte ( const uint8_t byNewInput ); - bool CheckCRC ( const uint32_t iCRC ) { return iCRC == GetCRC(); } - uint32_t GetCRC(); - -protected: - uint32_t iPoly; - uint32_t iBitOutMask; - uint32_t iStateShiftReg; -}; - - -// Mathematics utilities ------------------------------------------------------- -class LlconMath -{ -public: - static int round ( double x ) - { - return (int) ( ( x - floor ( x ) ) >= 0.5 ) ? ceil(x) : floor(x); - } -}; - - -// Precise time ---------------------------------------------------------------- -// required for ping measurement -class CPreciseTime -{ -public: -#ifdef _WIN32 - // for the Windows version we have to define a minimum timer precision - // -> set it to 1 ms - CPreciseTime() { timeBeginPeriod ( 1 ); } - virtual ~CPreciseTime() { timeEndPeriod ( 1 ); } -#endif - - // precise time (on Windows the QTime is not precise enough) - int elapsed() - { -#ifdef _WIN32 - return timeGetTime(); -#else - return QTime().elapsed(); -#endif - } -}; - - -/******************************************************************************\ -* Statistics * -\******************************************************************************/ -// Cycle time variance measurement --------------------------------------------- -// use for, e.g., measuring the variance of a timer -class CCycleTimeVariance -{ -public: - CCycleTimeVariance() : iBlockLengthAtSystemSampleRate ( 0 ), - dIntervalTime ( 0.0 ), iNewValueBoundFactor ( 0 ) {} - - void Init ( const int iNewBlockLengthAtSystemSampleRate, - const int iNewSystemSampleRateHz, - const int iHistoryLengthTimeSec, - const int iNewNewValueBoundFactor = MAX_NET_BUF_SIZE_NUM_BL ) - { - // store block size and new value bound factor - iBlockLengthAtSystemSampleRate = iNewBlockLengthAtSystemSampleRate; - iNewValueBoundFactor = iNewNewValueBoundFactor; - - // calculate interval time - dIntervalTime = static_cast ( - iBlockLengthAtSystemSampleRate ) * 1000 / iNewSystemSampleRateHz; - - // calculate actual moving average length and initialize buffer - RespTimeMoAvBuf.Init ( iHistoryLengthTimeSec * - iNewSystemSampleRateHz / iNewBlockLengthAtSystemSampleRate ); - } - - int GetBlockLength() { return iBlockLengthAtSystemSampleRate; } - - void Reset() - { - TimeLastBlock = PreciseTime.elapsed(); - RespTimeMoAvBuf.Reset(); - } - - double Update() - { - // add time difference - const int CurTime = PreciseTime.elapsed(); - - // we want to calculate the standard deviation (we assume that the mean - // is correct at the block period time) - const double dCurAddVal = - static_cast ( CurTime - TimeLastBlock ) - dIntervalTime; - -/* -// TEST -static FILE* pFile = fopen ( "c:\\temp\\test.dat", "w" ); -fprintf ( pFile, "%e %e\n", dCurAddVal, iNewValueBoundFactor * dIntervalTime ); -fflush ( pFile ); -// close;x=read('c:/temp/test.dat',-1,2);plot(x) -*/ - - // check if new value is in range (lower and upper bound) - if ( ( fabs ( dCurAddVal ) <= ( iNewValueBoundFactor * dIntervalTime ) ) )// && -// ( fabs ( dCurAddVal ) >= dIntervalTime ) ) - { - // add squared value - RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); - } - - // store old time value - TimeLastBlock = CurTime; - - return dCurAddVal; - } - - // return the standard deviation, for that we need to calculate - // the sqaure root - double GetStdDev() { return sqrt ( RespTimeMoAvBuf.GetAverage() ); } - - bool IsInitialized() { return RespTimeMoAvBuf.IsInitialized(); } - -protected: - CPreciseTime PreciseTime; - CMovingAv RespTimeMoAvBuf; - int TimeLastBlock; - int iBlockLengthAtSystemSampleRate; - double dIntervalTime; - int iNewValueBoundFactor; -}; - - -// Error rate measurement ------------------------------------------------------ -class CErrorRate -{ -public: - CErrorRate() {} - - void Init ( const int iHistoryLength, - const bool bNBlockOnDoubleErr = false ) - { - // initialize buffer (use "no data result" of 1.0 which stands for the - // worst error rate possible) - ErrorsMovAvBuf.Init ( iHistoryLength, 1.0f ); - - bPreviousState = true; - - // store setting - bBlockOnDoubleErrors = bNBlockOnDoubleErr; - } - - void Reset() - { - ErrorsMovAvBuf.Reset(); - bPreviousState = true; - } - - void Update ( const bool bState ) - { - // if two states were false, do not use the new value - if ( bBlockOnDoubleErrors && bPreviousState && bState ) - { - return; - } - - // add errors as values 0 and 1 to get correct error rate average - if ( bState ) - { - ErrorsMovAvBuf.Add ( 1.0f ); - } - else - { - ErrorsMovAvBuf.Add ( 0.0f ); - - } - - // store state - bPreviousState = bState; - } - - double GetAverage() { return ErrorsMovAvBuf.GetAverage(); } - -protected: - CMovingAv ErrorsMovAvBuf; - bool bBlockOnDoubleErrors; - bool bPreviousState; -}; - -#endif /* !defined ( UTIL_HOIH934256GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) */ +/******************************************************************************\ + * Copyright (c) 2004-2011 + * + * Author(s): + * Volker Fischer + * + ****************************************************************************** + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +\******************************************************************************/ + +#if !defined ( UTIL_HOIH934256GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) +#define UTIL_HOIH934256GEKJH98_3_43445KJIUHF1912__INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "global.h" +using namespace std; // because of the library: "vector" +#ifdef _WIN32 +# include "../windows/moc/aboutdlgbase.h" +# include +# include +#else +# ifdef _IS_QMAKE_CONFIG +# include "ui_aboutdlgbase.h" +# else +# include "moc/aboutdlgbase.h" +# endif +#endif + + +/* Definitions ****************************************************************/ +#define METER_FLY_BACK 2 + + +/* Global functions ***********************************************************/ +// converting double to short +inline short Double2Short ( const double dInput ) +{ + // lower bound + if ( dInput < _MINSHORT ) + { + return _MINSHORT; + } + + // upper bound + if ( dInput > _MAXSHORT ) + { + return _MAXSHORT; + } + + return (short) dInput; +} + +// debug error handling +void DebugError ( const QString& pchErDescr, + const QString& pchPar1Descr, + const double dPar1, + const QString& pchPar2Descr, + const double dPar2 ); + + +/******************************************************************************\ +* CVector Base Class * +\******************************************************************************/ +template class CVector : public std::vector +{ +public: + CVector() : iVectorSize ( 0 ) { pData = this->begin(); } + CVector ( const int iNeSi ) { Init(iNeSi); } + CVector ( const int iNeSi, const TData tInVa ) { Init ( iNeSi, tInVa ); } + + // Copy constructor: The order of the initialization list must not be + // changed. First, the base class must be initialized, then the pData + // pointer must be set to the new data source. The bit access is, by + // default, reset. + CVector ( const CVector& vecI ) : + std::vector ( static_cast&> ( vecI ) ), + iVectorSize ( vecI.Size() ) { pData = this->begin(); } + + void Init ( const int iNewSize ); + + // use this init to give all elements a defined value + void Init ( const int iNewSize, const TData tIniVal ); + void Reset ( const TData tResetVal ); + + void Enlarge ( const int iAddedSize ); + void Add ( const TData& tI ) { Enlarge ( 1 ); pData[iVectorSize - 1] = tI; } + + inline int Size() const { return iVectorSize; } + + // This operator allows for a l-value assignment of this object: + // CVector[x] = y is possible + inline TData& operator[] ( const int iPos ) { +#ifdef _DEBUG_ + if ( ( iPos < 0 ) || ( iPos > iVectorSize - 1 ) ) + { + DebugError ( "Writing vector out of bounds", "Vector size", + iVectorSize, "New parameter", iPos ); + } +#endif + return pData[iPos]; } + + inline TData operator[] ( const int iPos ) const { +#ifdef _DEBUG_ + if ( ( iPos < 0 ) || ( iPos > iVectorSize - 1 ) ) + { + DebugError ( "Reading vector out of bounds", "Vector size", + iVectorSize, "New parameter", iPos ); + } +#endif + return pData[iPos]; } + + inline CVector& operator= ( const CVector& vecI ) { +#ifdef _DEBUG_ + // Vectors which shall be copied MUST have same size! (If this is + // satisfied, the parameter "iVectorSize" must not be adjusted as + // a side effect) + if ( vecI.Size() != iVectorSize ) + { + DebugError ( "Vector operator=() different size", "Vector size", + iVectorSize, "New parameter", vecI.Size() ); + } +#endif + vector::operator= ( vecI ); + + // reset my data pointer in case, the operator=() of the base class + // did change the actual memory + pData = this->begin(); + + return *this; + } + +protected: + typename std::vector::iterator pData; + int iVectorSize; +}; + + +/* Implementation *************************************************************/ +template void CVector::Init ( const int iNewSize ) +{ + iVectorSize = iNewSize; + + // clear old buffer and reserve memory for new buffer, get iterator + // for pointer operations + this->clear(); + this->resize ( iNewSize ); + pData = this->begin(); +} + +template void CVector::Init ( const int iNewSize, + const TData tIniVal ) +{ + // call actual init routine + Init ( iNewSize ); + + // set values + Reset ( tIniVal ); +} + +template void CVector::Enlarge ( const int iAddedSize ) +{ + iVectorSize += iAddedSize; + this->resize ( iVectorSize ); + + // we have to reset the pointer since it could be that the vector size was + // zero before enlarging the vector + pData = this->begin(); +} + +template void CVector::Reset ( const TData tResetVal ) +{ + // set all values to reset value + for ( int i = 0; i < iVectorSize; i++ ) + { + pData[i] = tResetVal; + } +} + + +/******************************************************************************\ +* CFIFO Class (First In, First Out) * +\******************************************************************************/ +template class CFIFO : public CVector +{ +public: + CFIFO() : CVector(), iCurIdx ( 0 ) {} + CFIFO ( const int iNeSi ) : CVector(iNeSi), iCurIdx ( 0 ) {} + CFIFO ( const int iNeSi, const TData tInVa ) : + CVector ( iNeSi, tInVa ), iCurIdx ( 0 ) {} + + void Add ( const TData tNewD ); + inline TData Get() { return this->pData[iCurIdx]; } + + virtual void Init ( const int iNewSize ); + virtual void Init ( const int iNewSize, const TData tIniVal ); + +protected: + int iCurIdx; +}; + +template void CFIFO::Init ( const int iNewSize ) +{ + iCurIdx = 0; + CVector::Init ( iNewSize ); +} + +template void CFIFO::Init ( const int iNewSize, + const TData tIniVal ) +{ + iCurIdx = 0; + CVector::Init ( iNewSize, tIniVal ); +} + +template void CFIFO::Add ( const TData tNewD ) +{ + this->pData[iCurIdx] = tNewD; + + // increment index + iCurIdx++; + if ( iCurIdx >= this->iVectorSize ) + { + iCurIdx = 0; + } +} + + +/******************************************************************************\ +* CMovingAv Class (Moving Average) * +\******************************************************************************/ +template class CMovingAv : public CVector +{ +public: + CMovingAv() : + CVector(), + iCurIdx ( 0 ), + iNorm ( 0 ), + dCurAvResult ( 0 ), + dNoDataResult ( 0 ) {} + + void Add ( const TData tNewD ); + + void Init ( const int iNewSize, + const double dNNoDRes = 0 ); + + void Reset(); + + inline double GetAverage() + { + if ( this->iNorm == 0 ) + { + return dNoDataResult; + } + else + { + return dCurAvResult / this->iNorm; + } + } + + bool IsInitialized() { return ( this->iNorm == this->iVectorSize ); } + +protected: + int iCurIdx; + int iNorm; + double dCurAvResult; + double dNoDataResult; +}; + +template void CMovingAv::Init ( const int iNewSize, + const double dNNoDRes ) +{ + iNorm = 0; + iCurIdx = 0; + dCurAvResult = 0; // only for scalars! + dNoDataResult = dNNoDRes; + CVector::Init ( iNewSize ); +} + +template void CMovingAv::Reset() +{ + iNorm = 0; + iCurIdx = 0; + dCurAvResult = 0; // only for scalars! + CVector::Reset ( TData ( 0 ) ); +} + +template void CMovingAv::Add ( const TData tNewD ) +{ +/* + Optimized calculation of the moving average. We only add a new value and + subtract the old value from the result. We only need one addition and a + history buffer. +*/ + // subtract oldest value + dCurAvResult -= this->pData[iCurIdx]; + + // add new value and write in memory + dCurAvResult += tNewD; + this->pData[iCurIdx] = tNewD; + + // increase position pointer and test if wrap + iCurIdx++; + if ( iCurIdx >= this->iVectorSize ) + { + iCurIdx = 0; + } + + // take care of norm + if ( this->iNorm < this->iVectorSize ) + { + this->iNorm++; + } +} + + +/******************************************************************************\ +* GUI Utilities * +\******************************************************************************/ +// About dialog ---------------------------------------------------------------- +class CAboutDlg : public QDialog, private Ui_CAboutDlgBase +{ + Q_OBJECT + +public: + CAboutDlg ( QWidget* parent = 0 ); + + static QString GetVersionAndNameStr ( const bool bWithHtml = true ); +}; + + +// Help menu ------------------------------------------------------------------- +class CLlconHelpMenu : public QMenu +{ + Q_OBJECT + +public: + CLlconHelpMenu ( QWidget* parent = 0 ); + +protected: + CAboutDlg AboutDlg; + +public slots: + void OnHelpWhatsThis() { QWhatsThis::enterWhatsThisMode(); } + void OnHelpAbout() { AboutDlg.exec(); } + void OnHelpDownloadLink() + { QDesktopServices::openUrl ( QUrl ( LLCON_DOWNLOAD_URL ) ); } +}; + + +/******************************************************************************\ +* Other Classes * +\******************************************************************************/ +// Stereo signal level meter --------------------------------------------------- +class CStereoSignalLevelMeter +{ +public: + CStereoSignalLevelMeter() { Reset(); } + + void Update ( CVector& vecsAudio ); + double MicLevelLeft() { return CalcLogResult ( dCurLevelL ); } + double MicLevelRight() { return CalcLogResult ( dCurLevelR ); } + void Reset() { dCurLevelL = 0.0; dCurLevelR = 0.0; } + +protected: + double CalcLogResult ( const double& dLinearLevel ); + double UpdateCurLevel ( double dCurLevel, const short& sMax ); + + double dCurLevelL; + double dCurLevelR; +}; + + +// Host address ---------------------------------------------------------------- +class CHostAddress +{ +public: + enum EStringMode + { + SM_IP_PORT, + SM_IP_NO_LAST_BYTE, + SM_IP_NO_LAST_BYTE_PORT + }; + + CHostAddress() : + InetAddr ( static_cast ( 0 ) ), + iPort ( 0 ) {} + + CHostAddress ( const QHostAddress NInetAddr, + const quint16 iNPort ) : + InetAddr ( NInetAddr ), + iPort ( iNPort ) {} + + CHostAddress ( const CHostAddress& NHAddr ) : + InetAddr ( NHAddr.InetAddr ), + iPort ( NHAddr.iPort ) {} + + // copy operator + CHostAddress& operator= ( const CHostAddress& NHAddr ) + { + InetAddr = NHAddr.InetAddr; + iPort = NHAddr.iPort; + return *this; + } + + // compare operator + bool operator== ( const CHostAddress& CompAddr ) // compare operator + { + return ( ( CompAddr.InetAddr == InetAddr ) && + ( CompAddr.iPort == iPort ) ); + } + + QString toString ( const EStringMode eStringMode = SM_IP_PORT ) const + { + QString strReturn = InetAddr.toString(); + + // special case: for local host address, we do not replace the last byte + if ( ( ( eStringMode == SM_IP_NO_LAST_BYTE ) || + ( eStringMode == SM_IP_NO_LAST_BYTE_PORT ) ) && + ( InetAddr != QHostAddress ( QHostAddress::LocalHost ) ) ) + { + // replace last byte by an "x" + strReturn = strReturn.section ( ".", 0, 2 ) + ".x"; + } + + if ( ( eStringMode == SM_IP_PORT ) || + ( eStringMode == SM_IP_NO_LAST_BYTE_PORT ) ) + { + // add port number after a semicolon + strReturn += ":" + QString().setNum ( iPort ); + } + + return strReturn; + } + + QHostAddress InetAddr; + quint16 iPort; +}; + + +// Short info of a channel ----------------------------------------------------- +class CChannelShortInfo +{ +public: + CChannelShortInfo() : + iChanID ( 0 ), + iIpAddr ( 0 ), + strName ( "" ) {} + + CChannelShortInfo ( const int iNID, + const quint32 nIP, + const QString nN ) : + iChanID ( iNID ), + iIpAddr ( nIP ), + strName ( nN ) {} + + int iChanID; + quint32 iIpAddr; + QString strName; +}; + + +// Server info ----------------------------------------------------------------- +class CServerCoreInfo +{ +public: + CServerCoreInfo() : + iLocalPortNumber ( 0 ), + strName ( "" ), + strTopic ( "" ), + eCountry ( QLocale::AnyCountry ), + strCity ( "" ), + iMaxNumClients ( 0 ), + bPermanentOnline ( false ) {} + + CServerCoreInfo ( + const quint16 NLocPort, + const QString& NsName, + const QString& NsTopic, + const QLocale::Country& NeCountry, + const QString& NsCity, + const int NiMaxNumClients, + const bool NbPermOnline) : + iLocalPortNumber ( NLocPort ), + strName ( NsName ), + strTopic ( NsTopic ), + eCountry ( NeCountry ), + strCity ( NsCity ), + iMaxNumClients ( NiMaxNumClients ), + bPermanentOnline ( NbPermOnline ) {} + +public: + // local port number of the server + quint16 iLocalPortNumber; + + // name of the server + QString strName; + + // topic of the current jam session or server + QString strTopic; + + // country in which the server is located + QLocale::Country eCountry; + + // city in which the server is located + QString strCity; + + // maximum number of clients which can connect to the server at the same + // time + int iMaxNumClients; + + // is the server permanently online or not (flag) + bool bPermanentOnline; +}; + +class CServerInfo : public CServerCoreInfo +{ +public: + CServerInfo() : + CServerCoreInfo ( 0, + "", + "", + QLocale::AnyCountry, + "", + 0, + false ), HostAddr ( CHostAddress() ) {} + + CServerInfo ( + const CHostAddress& NHAddr, + const quint16 NLocPort, + const QString& NsName, + const QString& NsTopic, + const QLocale::Country& NeCountry, + const QString& NsCity, + const int NiMaxNumClients, + const bool NbPermOnline) : + CServerCoreInfo ( NLocPort, + NsName, + NsTopic, + NeCountry, + NsCity, + NiMaxNumClients, + NbPermOnline ), HostAddr ( NHAddr ) {} + +public: + // internet address of the server + CHostAddress HostAddr; +}; + + +// Audio compression type enum ------------------------------------------------- +enum EAudComprType +{ + CT_NONE = 0, + CT_CELT = 1 +}; + + +// Get data status enum -------------------------------------------------------- +enum EGetDataStat +{ + GS_BUFFER_OK, + GS_BUFFER_UNDERRUN, + GS_CHAN_NOW_DISCONNECTED, + GS_CHAN_NOT_CONNECTED +}; + + +// GUI design enum ------------------------------------------------------------- +enum EGUIDesign +{ + GD_STANDARD = 0, + GD_ORIGINAL = 1 +}; + + +// Network transport properties ------------------------------------------------ +class CNetworkTransportProps +{ +public: + CNetworkTransportProps() : + iBaseNetworkPacketSize ( 0 ), + iBlockSizeFact ( 0 ), + iNumAudioChannels ( 0 ), + iSampleRate ( 0 ), + eAudioCodingType ( CT_NONE ), + iAudioCodingArg ( 0 ) {} + + CNetworkTransportProps ( const uint32_t iNBNPS, + const uint16_t iNBSF, + const uint32_t iNNACH, + const uint32_t iNSR, + const EAudComprType eNACT, + const uint32_t iNVers, + const int32_t iNACA ) : + iBaseNetworkPacketSize ( iNBNPS ), + iBlockSizeFact ( iNBSF ), + iNumAudioChannels ( iNNACH ), + iSampleRate ( iNSR ), + eAudioCodingType ( eNACT ), + iVersion ( iNVers ), + iAudioCodingArg ( iNACA ) {} + + uint32_t iBaseNetworkPacketSize; + uint16_t iBlockSizeFact; + uint32_t iNumAudioChannels; + uint32_t iSampleRate; + EAudComprType eAudioCodingType; + uint32_t iVersion; + int32_t iAudioCodingArg; +}; + + +// Network utility functions --------------------------------------------------- +class LlconNetwUtil +{ +public: + static bool ParseNetworkAddress ( QString strAddress, + CHostAddress& HostAddress ); +}; + + +// Audio reverbration ---------------------------------------------------------- +class CAudioReverb +{ +public: + CAudioReverb() {} + + void Init ( const int iSampleRate, const double rT60 = (double) 5.0 ); + void Clear(); + double ProcessSample ( const double input ); + +protected: + void setT60 ( const double rT60, const int iSampleRate ); + bool isPrime ( const int number ); + + CFIFO allpassDelays_[3]; + CFIFO combDelays_[4]; + double allpassCoefficient_; + double combCoefficient_[4]; +}; + + +// CRC ------------------------------------------------------------------------- +class CCRC +{ +public: + CCRC() : iPoly ( ( 1 << 5 ) | ( 1 << 12 ) ), iBitOutMask ( 1 << 16 ) + { Reset(); } + + void Reset(); + void AddByte ( const uint8_t byNewInput ); + bool CheckCRC ( const uint32_t iCRC ) { return iCRC == GetCRC(); } + uint32_t GetCRC(); + +protected: + uint32_t iPoly; + uint32_t iBitOutMask; + uint32_t iStateShiftReg; +}; + + +// Mathematics utilities ------------------------------------------------------- +class LlconMath +{ +public: + static int round ( double x ) + { + return (int) ( ( x - floor ( x ) ) >= 0.5 ) ? ceil(x) : floor(x); + } +}; + + +// Precise time ---------------------------------------------------------------- +// required for ping measurement +class CPreciseTime +{ +public: +#ifdef _WIN32 + // for the Windows version we have to define a minimum timer precision + // -> set it to 1 ms + CPreciseTime() { timeBeginPeriod ( 1 ); } + virtual ~CPreciseTime() { timeEndPeriod ( 1 ); } +#endif + + // precise time (on Windows the QTime is not precise enough) + int elapsed() + { +#ifdef _WIN32 + return timeGetTime(); +#else + return QTime().elapsed(); +#endif + } +}; + + +/******************************************************************************\ +* Statistics * +\******************************************************************************/ +// Cycle time variance measurement --------------------------------------------- +// use for, e.g., measuring the variance of a timer +class CCycleTimeVariance +{ +public: + CCycleTimeVariance() : iBlockLengthAtSystemSampleRate ( 0 ), + dIntervalTime ( 0.0 ), iNewValueBoundFactor ( 0 ) {} + + void Init ( const int iNewBlockLengthAtSystemSampleRate, + const int iNewSystemSampleRateHz, + const int iHistoryLengthTimeSec, + const int iNewNewValueBoundFactor = MAX_NET_BUF_SIZE_NUM_BL ) + { + // store block size and new value bound factor + iBlockLengthAtSystemSampleRate = iNewBlockLengthAtSystemSampleRate; + iNewValueBoundFactor = iNewNewValueBoundFactor; + + // calculate interval time + dIntervalTime = static_cast ( + iBlockLengthAtSystemSampleRate ) * 1000 / iNewSystemSampleRateHz; + + // calculate actual moving average length and initialize buffer + RespTimeMoAvBuf.Init ( iHistoryLengthTimeSec * + iNewSystemSampleRateHz / iNewBlockLengthAtSystemSampleRate ); + } + + int GetBlockLength() { return iBlockLengthAtSystemSampleRate; } + + void Reset() + { + TimeLastBlock = PreciseTime.elapsed(); + RespTimeMoAvBuf.Reset(); + } + + double Update() + { + // add time difference + const int CurTime = PreciseTime.elapsed(); + + // we want to calculate the standard deviation (we assume that the mean + // is correct at the block period time) + const double dCurAddVal = + static_cast ( CurTime - TimeLastBlock ) - dIntervalTime; + +/* +// TEST +static FILE* pFile = fopen ( "c:\\temp\\test.dat", "w" ); +fprintf ( pFile, "%e %e\n", dCurAddVal, iNewValueBoundFactor * dIntervalTime ); +fflush ( pFile ); +// close;x=read('c:/temp/test.dat',-1,2);plot(x) +*/ + + // check if new value is in range (lower and upper bound) + if ( ( fabs ( dCurAddVal ) <= ( iNewValueBoundFactor * dIntervalTime ) ) )// && +// ( fabs ( dCurAddVal ) >= dIntervalTime ) ) + { + // add squared value + RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); + } + + // store old time value + TimeLastBlock = CurTime; + + return dCurAddVal; + } + + // return the standard deviation, for that we need to calculate + // the sqaure root + double GetStdDev() { return sqrt ( RespTimeMoAvBuf.GetAverage() ); } + + bool IsInitialized() { return RespTimeMoAvBuf.IsInitialized(); } + +protected: + CPreciseTime PreciseTime; + CMovingAv RespTimeMoAvBuf; + int TimeLastBlock; + int iBlockLengthAtSystemSampleRate; + double dIntervalTime; + int iNewValueBoundFactor; +}; + + +// Error rate measurement ------------------------------------------------------ +class CErrorRate +{ +public: + CErrorRate() {} + + void Init ( const int iHistoryLength, + const bool bNBlockOnDoubleErr = false ) + { + // initialize buffer (use "no data result" of 1.0 which stands for the + // worst error rate possible) + ErrorsMovAvBuf.Init ( iHistoryLength, 1.0 ); + + bPreviousState = true; + + // store setting + bBlockOnDoubleErrors = bNBlockOnDoubleErr; + } + + void Reset() + { + ErrorsMovAvBuf.Reset(); + bPreviousState = true; + } + + void Update ( const bool bState ) + { + // if two states were false, do not use the new value + if ( bBlockOnDoubleErrors && bPreviousState && bState ) + { + return; + } + + // add errors as values 0 and 1 to get correct error rate average + if ( bState ) + { + ErrorsMovAvBuf.Add ( 1 ); + } + else + { + ErrorsMovAvBuf.Add ( 0 ); + + } + + // store state + bPreviousState = bState; + } + + double GetAverage() { return ErrorsMovAvBuf.GetAverage(); } + +protected: + CMovingAv ErrorsMovAvBuf; + bool bBlockOnDoubleErrors; + bool bPreviousState; +}; + +#endif /* !defined ( UTIL_HOIH934256GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) */