Overte C++ Documentation
InboundAudioStream.h
1 //
2 // InboundAudioStream.h
3 // libraries/audio/src
4 //
5 // Created by Yixin Wang on 7/17/2014.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_InboundAudioStream_h
13 #define hifi_InboundAudioStream_h
14 
15 #include <Node.h>
16 #include <NodeData.h>
17 #include <NumericalConstants.h>
18 #include <udt/PacketHeaders.h>
19 #include <ReceivedMessage.h>
20 #include <StDev.h>
21 
22 #include <plugins/CodecPlugin.h>
23 
24 #include "AudioRingBuffer.h"
25 #include "MovingMinMaxAvg.h"
26 #include "SequenceNumberStats.h"
27 #include "AudioStreamStats.h"
28 #include "TimeWeightedAvg.h"
29 
30 // Audio Env bitset
31 const int HAS_REVERB_BIT = 0; // 1st bit
32 
33 using StreamSequenceNumber = quint16;
34 
35 class InboundAudioStream : public NodeData {
36  Q_OBJECT
37 
38 public:
39  // settings
40  static const bool DEFAULT_DYNAMIC_JITTER_BUFFER_ENABLED;
41  static const int DEFAULT_STATIC_JITTER_FRAMES;
42  // legacy (now static) settings
43  static const int MAX_FRAMES_OVER_DESIRED;
44  static const int WINDOW_STARVE_THRESHOLD;
45  static const int WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES;
46  static const int WINDOW_SECONDS_FOR_DESIRED_REDUCTION;
47  // unused (eradicated) settings
48  static const bool USE_STDEV_FOR_JITTER;
49  static const bool REPETITION_WITH_FADE;
50 
51  InboundAudioStream() = delete;
52  InboundAudioStream(int numChannels, int numFrames, int numBlocks, int numStaticJitterBlocks);
53  ~InboundAudioStream();
54 
55  void reset();
56  virtual void resetStats();
57  void clearBuffer();
58 
59  virtual int parseData(ReceivedMessage& packet) override;
60 
61  int popFrames(int maxFrames, bool allOrNothing);
62  int popSamples(int maxSamples, bool allOrNothing);
63 
64  bool lastPopSucceeded() const { return _lastPopSucceeded; };
65  const AudioRingBuffer::ConstIterator& getLastPopOutput() const { return _lastPopOutput; }
66 
67  quint64 usecsSinceLastPacket() { return usecTimestampNow() - _lastPacketReceivedTime; }
68 
69  void setToStarved();
70 
71  void setDynamicJitterBufferEnabled(bool enable);
72  void setStaticJitterBufferFrames(int staticJitterBufferFrames);
73 
74  virtual AudioStreamStats getAudioStreamStats() const;
75 
77  int getCalculatedJitterBufferFrames() const { return _calculatedJitterBufferFrames; }
78 
79  bool dynamicJitterBufferEnabled() const { return _dynamicJitterBufferEnabled; }
80  int getStaticJitterBufferFrames() { return _staticJitterBufferFrames; }
81  int getDesiredJitterBufferFrames() { return _desiredJitterBufferFrames; }
82 
83  int getNumFrameSamples() const { return _ringBuffer.getNumFrameSamples(); }
84  int getFrameCapacity() const { return _ringBuffer.getFrameCapacity(); }
85  int getFramesAvailable() const { return _ringBuffer.framesAvailable(); }
86  double getFramesAvailableAverage() const { return _framesAvailableStat.getAverage(); }
87  int getSamplesAvailable() const { return _ringBuffer.samplesAvailable(); }
88 
89  bool isStarved() const { return _isStarved; }
90  bool hasStarted() const { return _hasStarted; }
91 
92  int getConsecutiveNotMixedCount() const { return _consecutiveNotMixedCount; }
93  int getStarveCount() const { return _starveCount; }
94  int getSilentFramesDropped() const { return _silentFramesDropped; }
95  int getOverflowCount() const { return _ringBuffer.getOverflowCount(); }
96 
97  int getPacketsReceived() const { return _incomingSequenceNumberStats.getReceived(); }
98 
99  bool hasReverb() const { return _hasReverb; }
100  float getRevebTime() const { return _reverbTime; }
101  float getWetLevel() const { return _wetLevel; }
102  void setReverb(float reverbTime, float wetLevel);
103  void clearReverb() { _hasReverb = false; }
104 
105  void setupCodec(CodecPluginPointer codec, const QString& codecName, int numChannels);
106  void cleanupCodec();
107 
108 signals:
109  void mismatchedAudioCodec(SharedNodePointer sendingNode, const QString& currentCodec, const QString& recievedCodec);
110 
111 public slots:
115  void perSecondCallbackForUpdatingStats();
116 
117 private:
118  void packetReceivedUpdateTimingStats();
119 
120  void popSamplesNoCheck(int samples);
121  void framesAvailableChanged();
122 
123 protected:
124  // disallow copying of InboundAudioStream objects
125  InboundAudioStream(const InboundAudioStream&);
126  InboundAudioStream& operator= (const InboundAudioStream&);
127 
131  virtual int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& networkSamples);
132 
135  virtual int parseAudioData(const QByteArray& packetAfterStreamProperties);
136 
138  virtual int lostAudioData(int numPackets);
139 
141  virtual int writeDroppableSilentFrames(int silentFrames);
142 
143 protected:
144 
145  AudioRingBuffer _ringBuffer;
146  int _numChannels;
147 
148  bool _lastPopSucceeded { false };
149  AudioRingBuffer::ConstIterator _lastPopOutput;
150 
151  bool _dynamicJitterBufferEnabled { DEFAULT_DYNAMIC_JITTER_BUFFER_ENABLED };
152  int _staticJitterBufferFrames { DEFAULT_STATIC_JITTER_FRAMES };
153  int _desiredJitterBufferFrames;
154 
155  bool _isStarved { true };
156  bool _hasStarted { false };
157 
158  // stats
159 
160  int _consecutiveNotMixedCount { 0 };
161  int _starveCount { 0 };
162  int _silentFramesDropped { 0 };
163  int _oldFramesDropped { 0 };
164 
165  SequenceNumberStats _incomingSequenceNumberStats;
166 
167  quint64 _lastPacketReceivedTime { 0 };
168  MovingMinMaxAvg<quint64> _timeGapStatsForDesiredCalcOnTooManyStarves { 0, WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES };
169  int _calculatedJitterBufferFrames { 0 };
170  MovingMinMaxAvg<quint64> _timeGapStatsForDesiredReduction { 0, WINDOW_SECONDS_FOR_DESIRED_REDUCTION };
171 
172  RingBufferHistory<quint64> _starveHistory;
173 
174  TimeWeightedAvg<int> _framesAvailableStat;
175  MovingMinMaxAvg<float> _unplayedMs;
176 
177  // this value is periodically updated with the time-weighted avg from _framesAvailableStat. it is only used for
178  // dropping silent frames right now.
179  int _currentJitterBufferFrames { 0 };
180 
181  MovingMinMaxAvg<quint64> _timeGapStatsForStatsPacket;
182 
183  // Reverb properties
184  bool _hasReverb { false };
185  float _reverbTime { 0.0f };
186  float _wetLevel { 0.0f };
187 
188  CodecPluginPointer _codec;
189  QString _selectedCodecName;
190  QMutex _decoderMutex;
191  Decoder* _decoder { nullptr };
192  int _mismatchedAudioCodecCount { 0 };
193 };
194 
195 float calculateRepeatedFrameFadeFactor(int indexOfRepeat);
196 
197 #endif // hifi_InboundAudioStream_h