-
Notifications
You must be signed in to change notification settings - Fork 227
/
Copy pathclient.h
437 lines (355 loc) · 16.5 KB
/
client.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
/******************************************************************************\
* Copyright (c) 2004-2022
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
\******************************************************************************/
#pragma once
#include <QHostAddress>
#include <QHostInfo>
#include <QString>
#include <QDateTime>
#include <QMutex>
#ifdef USE_OPUS_SHARED_LIB
# include "opus/opus_custom.h"
#else
# include "opus_custom.h"
#endif
#include "global.h"
#include "socket.h"
#include "channel.h"
#include "util.h"
#include "buffer.h"
#include "signalhandler.h"
#if defined( _WIN32 ) && !defined( JACK_ON_WINDOWS )
# include "sound/asio/sound.h"
#else
# if ( defined( Q_OS_MACX ) ) && !defined( JACK_REPLACES_COREAUDIO )
# include "sound/coreaudio-mac/sound.h"
# else
# if defined( Q_OS_IOS )
# include "sound/coreaudio-ios/sound.h"
# else
# ifdef ANDROID
# include "sound/oboe/sound.h"
# else
# include "sound/jack/sound.h"
# ifndef JACK_ON_WINDOWS // these headers are not available in Windows OS
# include <sched.h>
# include <netdb.h>
# endif
# include <socket.h>
# endif
# endif
# endif
#endif
/* Definitions ****************************************************************/
// audio in fader range
#define AUD_FADER_IN_MIN 0
#define AUD_FADER_IN_MAX 100
#define AUD_FADER_IN_MIDDLE ( AUD_FADER_IN_MAX / 2 )
// audio reverberation range
#define AUD_REVERB_MAX 100
// default delay period between successive gain updates (ms)
// this will be increased to double the ping time if connected to a distant server
#define DEFAULT_GAIN_DELAY_PERIOD_MS 50
// OPUS number of coded bytes per audio packet
// TODO we have to use new numbers for OPUS to avoid that old CELT packets
// are used in the OPUS decoder (which gives a bad noise output signal).
// Later on when the CELT is completely removed we could set the OPUS
// numbers back to the original CELT values (to reduce network load)
// calculation to get from the number of bytes to the code rate in bps:
// rate [pbs] = Fs / L * N * 8, where
// Fs: sampling rate (SYSTEM_SAMPLE_RATE_HZ)
// L: number of samples per packet (SYSTEM_FRAME_SIZE_SAMPLES)
// N: number of bytes per packet (values below)
#define OPUS_NUM_BYTES_MONO_LOW_QUALITY 12
#define OPUS_NUM_BYTES_MONO_NORMAL_QUALITY 22
#define OPUS_NUM_BYTES_MONO_HIGH_QUALITY 36
#define OPUS_NUM_BYTES_MONO_LOW_QUALITY_DBLE_FRAMESIZE 25
#define OPUS_NUM_BYTES_MONO_NORMAL_QUALITY_DBLE_FRAMESIZE 45
#define OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE 82
#define OPUS_NUM_BYTES_STEREO_LOW_QUALITY 24
#define OPUS_NUM_BYTES_STEREO_NORMAL_QUALITY 35
#define OPUS_NUM_BYTES_STEREO_HIGH_QUALITY 73
#define OPUS_NUM_BYTES_STEREO_LOW_QUALITY_DBLE_FRAMESIZE 47
#define OPUS_NUM_BYTES_STEREO_NORMAL_QUALITY_DBLE_FRAMESIZE 71
#define OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE 165
/* Classes ********************************************************************/
class CClient : public QObject
{
Q_OBJECT
public:
CClient ( const quint16 iPortNumber,
const quint16 iQosNumber,
const QString& strConnOnStartupAddress,
const QString& strMIDISetup,
const bool bNoAutoJackConnect,
const QString& strNClientName,
const bool bNEnableIPv6,
const bool bNMuteMeInPersonalMix );
virtual ~CClient();
void Start();
void Stop();
bool IsRunning() { return Sound.IsRunning(); }
bool IsCallbackEntered() const { return Sound.IsCallbackEntered(); }
bool SetServerAddr ( QString strNAddr );
double GetLevelForMeterdBLeft() { return SignalLevelMeter.GetLevelForMeterdBLeftOrMono(); }
double GetLevelForMeterdBRight() { return SignalLevelMeter.GetLevelForMeterdBRight(); }
bool GetAndResetbJitterBufferOKFlag();
bool IsConnected() { return Channel.IsConnected(); }
EGUIDesign GetGUIDesign() const { return eGUIDesign; }
void SetGUIDesign ( const EGUIDesign eNGD ) { eGUIDesign = eNGD; }
EMeterStyle GetMeterStyle() const { return eMeterStyle; }
void SetMeterStyle ( const EMeterStyle eNMT ) { eMeterStyle = eNMT; }
EAudioQuality GetAudioQuality() const { return eAudioQuality; }
void SetAudioQuality ( const EAudioQuality eNAudioQuality );
EAudChanConf GetAudioChannels() const { return eAudioChannelConf; }
void SetAudioChannels ( const EAudChanConf eNAudChanConf );
int GetAudioInFader() const { return iAudioInFader; }
void SetAudioInFader ( const int iNV ) { iAudioInFader = iNV; }
int GetReverbLevel() const { return iReverbLevel; }
void SetReverbLevel ( const int iNL ) { iReverbLevel = iNL; }
bool IsReverbOnLeftChan() const { return bReverbOnLeftChan; }
void SetReverbOnLeftChan ( const bool bIL )
{
bReverbOnLeftChan = bIL;
AudioReverb.Clear();
}
void SetDoAutoSockBufSize ( const bool bValue );
bool GetDoAutoSockBufSize() const { return Channel.GetDoAutoSockBufSize(); }
void SetSockBufNumFrames ( const int iNumBlocks, const bool bPreserve = false ) { Channel.SetSockBufNumFrames ( iNumBlocks, bPreserve ); }
int GetSockBufNumFrames() { return Channel.GetSockBufNumFrames(); }
void SetServerSockBufNumFrames ( const int iNumBlocks )
{
iServerSockBufNumFrames = iNumBlocks;
// if auto setting is disabled, inform the server about the new size
if ( !GetDoAutoSockBufSize() )
{
Channel.CreateJitBufMes ( iServerSockBufNumFrames );
}
}
int GetServerSockBufNumFrames() { return iServerSockBufNumFrames; }
int GetUploadRateKbps() { return Channel.GetUploadRateKbps(); }
// sound card device selection
QStringList GetSndCrdDevNames() { return Sound.GetDevNames(); }
QString SetSndCrdDev ( const QString strNewDev );
QString GetSndCrdDev() { return Sound.GetDev(); }
void OpenSndCrdDriverSetup() { Sound.OpenDriverSetup(); }
// sound card channel selection
int GetSndCrdNumInputChannels() { return Sound.GetNumInputChannels(); }
QString GetSndCrdInputChannelName ( const int iDiD ) { return Sound.GetInputChannelName ( iDiD ); }
void SetSndCrdLeftInputChannel ( const int iNewChan );
void SetSndCrdRightInputChannel ( const int iNewChan );
int GetSndCrdLeftInputChannel() { return Sound.GetLeftInputChannel(); }
int GetSndCrdRightInputChannel() { return Sound.GetRightInputChannel(); }
int GetSndCrdNumOutputChannels() { return Sound.GetNumOutputChannels(); }
QString GetSndCrdOutputChannelName ( const int iDiD ) { return Sound.GetOutputChannelName ( iDiD ); }
void SetSndCrdLeftOutputChannel ( const int iNewChan );
void SetSndCrdRightOutputChannel ( const int iNewChan );
int GetSndCrdLeftOutputChannel() { return Sound.GetLeftOutputChannel(); }
int GetSndCrdRightOutputChannel() { return Sound.GetRightOutputChannel(); }
void SetSndCrdPrefFrameSizeFactor ( const int iNewFactor );
int GetSndCrdPrefFrameSizeFactor() { return iSndCrdPrefFrameSizeFactor; }
void SetEnableOPUS64 ( const bool eNEnableOPUS64 );
bool GetEnableOPUS64() { return bEnableOPUS64; }
int GetSndCrdActualMonoBlSize()
{
// the actual sound card mono block size depends on whether a
// sound card conversion buffer is used or not
if ( bSndCrdConversionBufferRequired )
{
return iSndCardMonoBlockSizeSamConvBuff;
}
else
{
return iMonoBlockSizeSam;
}
}
int GetSystemMonoBlSize() { return iMonoBlockSizeSam; }
int GetSndCrdConvBufAdditionalDelayMonoBlSize()
{
if ( bSndCrdConversionBufferRequired )
{
// by introducing the conversion buffer we also introduce additional
// delay which equals the "internal" mono buffer size
return iMonoBlockSizeSam;
}
else
{
return 0;
}
}
bool GetFraSiFactPrefSupported() { return bFraSiFactPrefSupported; }
bool GetFraSiFactDefSupported() { return bFraSiFactDefSupported; }
bool GetFraSiFactSafeSupported() { return bFraSiFactSafeSupported; }
void SetMuteOutStream ( const bool bDoMute ) { bMuteOutStream = bDoMute; }
void SetRemoteChanGain ( const int iId, const float fGain, const bool bIsMyOwnFader );
void OnTimerRemoteChanGain();
void StartDelayTimer();
void SetRemoteChanPan ( const int iId, const float fPan ) { Channel.SetRemoteChanPan ( iId, fPan ); }
void SetInputBoost ( const int iNewBoost ) { iInputBoost = iNewBoost; }
void SetRemoteInfo() { Channel.SetRemoteInfo ( ChannelInfo ); }
void CreateChatTextMes ( const QString& strChatText ) { Channel.CreateChatTextMes ( strChatText ); }
void CreateCLPingMes() { ConnLessProtocol.CreateCLPingMes ( Channel.GetAddress(), PreparePingMessage() ); }
void CreateCLServerListPingMes ( const CHostAddress& InetAddr )
{
ConnLessProtocol.CreateCLPingWithNumClientsMes ( InetAddr, PreparePingMessage(), 0 /* dummy */ );
}
void CreateCLServerListReqVerAndOSMes ( const CHostAddress& InetAddr ) { ConnLessProtocol.CreateCLReqVersionAndOSMes ( InetAddr ); }
void CreateCLServerListReqConnClientsListMes ( const CHostAddress& InetAddr ) { ConnLessProtocol.CreateCLReqConnClientsListMes ( InetAddr ); }
void CreateCLReqServerListMes ( const CHostAddress& InetAddr ) { ConnLessProtocol.CreateCLReqServerListMes ( InetAddr ); }
int EstimatedOverallDelay ( const int iPingTimeMs );
void GetBufErrorRates ( CVector<double>& vecErrRates, double& dLimit, double& dMaxUpLimit )
{
Channel.GetBufErrorRates ( vecErrRates, dLimit, dMaxUpLimit );
}
// settings
CChannelCoreInfo ChannelInfo;
QString strClientName;
protected:
// callback function must be static, otherwise it does not work
static void AudioCallback ( CVector<short>& psData, void* arg );
void Init();
void ProcessSndCrdAudioData ( CVector<short>& vecsStereoSndCrd );
void ProcessAudioDataIntern ( CVector<short>& vecsStereoSndCrd );
int PreparePingMessage();
int EvaluatePingMessage ( const int iMs );
void CreateServerJitterBufferMessage();
// only one channel is needed for client application
CChannel Channel;
CProtocol ConnLessProtocol;
// audio encoder/decoder
OpusCustomMode* Opus64Mode;
OpusCustomEncoder* Opus64EncoderMono;
OpusCustomDecoder* Opus64DecoderMono;
OpusCustomEncoder* Opus64EncoderStereo;
OpusCustomDecoder* Opus64DecoderStereo;
OpusCustomMode* OpusMode;
OpusCustomEncoder* OpusEncoderMono;
OpusCustomDecoder* OpusDecoderMono;
OpusCustomEncoder* OpusEncoderStereo;
OpusCustomDecoder* OpusDecoderStereo;
OpusCustomEncoder* CurOpusEncoder;
OpusCustomDecoder* CurOpusDecoder;
EAudComprType eAudioCompressionType;
int iCeltNumCodedBytes;
int iOPUSFrameSizeSamples;
EAudioQuality eAudioQuality;
EAudChanConf eAudioChannelConf;
int iNumAudioChannels;
bool bIsInitializationPhase;
bool bMuteOutStream;
float fMuteOutStreamGain;
CVector<unsigned char> vecCeltData;
CHighPrioSocket Socket;
CSound Sound;
CStereoSignalLevelMeter SignalLevelMeter;
CVector<uint8_t> vecbyNetwData;
int iAudioInFader;
bool bReverbOnLeftChan;
int iReverbLevel;
CAudioReverb AudioReverb;
int iInputBoost;
int iSndCrdPrefFrameSizeFactor;
int iSndCrdFrameSizeFactor;
bool bSndCrdConversionBufferRequired;
int iSndCardMonoBlockSizeSamConvBuff;
CBuffer<int16_t> SndCrdConversionBufferIn;
CBuffer<int16_t> SndCrdConversionBufferOut;
CVector<int16_t> vecDataConvBuf;
CVector<int16_t> vecsStereoSndCrdMuteStream;
CVector<int16_t> vecZeros;
bool bFraSiFactPrefSupported;
bool bFraSiFactDefSupported;
bool bFraSiFactSafeSupported;
int iMonoBlockSizeSam;
int iStereoBlockSizeSam;
EGUIDesign eGUIDesign;
EMeterStyle eMeterStyle;
bool bEnableAudioAlerts;
bool bEnableOPUS64;
bool bJitterBufferOK;
bool bEnableIPv6;
bool bMuteMeInPersonalMix;
QMutex MutexDriverReinit;
// server settings
int iServerSockBufNumFrames;
// for ping measurement
QElapsedTimer PreciseTime;
// for gain rate limiting
QMutex MutexGain;
QTimer TimerGain;
int minGainId;
int maxGainId;
float oldGain[MAX_NUM_CHANNELS];
float newGain[MAX_NUM_CHANNELS];
int iCurPingTime;
CSignalHandler* pSignalHandler;
protected slots:
void OnHandledSignal ( int sigNum );
void OnSendProtMessage ( CVector<uint8_t> vecMessage );
void OnInvalidPacketReceived ( CHostAddress RecHostAddr );
void OnDetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData, int iRecID, CHostAddress RecHostAddr );
void OnReqJittBufSize() { CreateServerJitterBufferMessage(); }
void OnJittBufSizeChanged ( int iNewJitBufSize );
void OnReqChanInfo() { Channel.SetRemoteInfo ( ChannelInfo ); }
void OnNewConnection();
void OnCLDisconnection ( CHostAddress InetAddr )
{
if ( InetAddr == Channel.GetAddress() )
{
emit Disconnected();
}
}
void OnCLPingReceived ( CHostAddress InetAddr, int iMs );
void OnSendCLProtMessage ( CHostAddress InetAddr, CVector<uint8_t> vecMessage );
void OnCLPingWithNumClientsReceived ( CHostAddress InetAddr, int iMs, int iNumClients );
void OnSndCrdReinitRequest ( int iSndCrdResetType );
void OnControllerInFaderLevel ( int iChannelIdx, int iValue );
void OnControllerInPanValue ( int iChannelIdx, int iValue );
void OnControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo );
void OnControllerInFaderIsMute ( int iChannelIdx, bool bIsMute );
void OnControllerInMuteMyself ( bool bMute );
void OnClientIDReceived ( int iChanID );
void OnConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
signals:
void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
void ChatTextReceived ( QString strChatText );
void ClientIDReceived ( int iChanID );
void MuteStateHasChangedReceived ( int iChanID, bool bIsMuted );
void LicenceRequired ( ELicenceType eLicenceType );
void VersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion );
void PingTimeReceived ( int iPingTime );
void RecorderStateReceived ( ERecorderState eRecorderState );
void CLServerListReceived ( CHostAddress InetAddr, CVector<CServerInfo> vecServerInfo );
void CLRedServerListReceived ( CHostAddress InetAddr, CVector<CServerInfo> vecServerInfo );
void CLConnClientsListMesReceived ( CHostAddress InetAddr, CVector<CChannelInfo> vecChanInfo );
void CLPingTimeWithNumClientsReceived ( CHostAddress InetAddr, int iPingTime, int iNumClients );
void CLVersionAndOSReceived ( CHostAddress InetAddr, COSUtil::EOpSystemType eOSType, QString strVersion );
void CLChannelLevelListReceived ( CHostAddress InetAddr, CVector<uint16_t> vecLevelList );
void Disconnected();
void SoundDeviceChanged ( QString strError );
void ControllerInFaderLevel ( int iChannelIdx, int iValue );
void ControllerInPanValue ( int iChannelIdx, int iValue );
void ControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo );
void ControllerInFaderIsMute ( int iChannelIdx, bool bIsMute );
void ControllerInMuteMyself ( bool bMute );
};