1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ 12 #define MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <atomic> 18 19 #include "api/task_queue/task_queue_factory.h" 20 #include "modules/audio_device/include/audio_device_defines.h" 21 #include "rtc_base/buffer.h" 22 #include "rtc_base/synchronization/mutex.h" 23 #include "rtc_base/task_queue.h" 24 #include "rtc_base/thread_annotations.h" 25 #include "rtc_base/thread_checker.h" 26 27 namespace webrtc { 28 29 // Delta times between two successive playout callbacks are limited to this 30 // value before added to an internal array. 31 const size_t kMaxDeltaTimeInMs = 500; 32 // TODO(henrika): remove when no longer used by external client. 33 const size_t kMaxBufferSizeBytes = 3840; // 10ms in stereo @ 96kHz 34 35 class AudioDeviceBuffer { 36 public: 37 enum LogState { 38 LOG_START = 0, 39 LOG_STOP, 40 LOG_ACTIVE, 41 }; 42 43 struct Stats { ResetRecStatsStats44 void ResetRecStats() { 45 rec_callbacks = 0; 46 rec_samples = 0; 47 max_rec_level = 0; 48 } 49 ResetPlayStatsStats50 void ResetPlayStats() { 51 play_callbacks = 0; 52 play_samples = 0; 53 max_play_level = 0; 54 } 55 56 // Total number of recording callbacks where the source provides 10ms audio 57 // data each time. 58 uint64_t rec_callbacks = 0; 59 60 // Total number of playback callbacks where the sink asks for 10ms audio 61 // data each time. 62 uint64_t play_callbacks = 0; 63 64 // Total number of recorded audio samples. 65 uint64_t rec_samples = 0; 66 67 // Total number of played audio samples. 68 uint64_t play_samples = 0; 69 70 // Contains max level (max(abs(x))) of recorded audio packets over the last 71 // 10 seconds where a new measurement is done twice per second. The level 72 // is reset to zero at each call to LogStats(). 73 int16_t max_rec_level = 0; 74 75 // Contains max level of recorded audio packets over the last 10 seconds 76 // where a new measurement is done twice per second. 77 int16_t max_play_level = 0; 78 }; 79 80 explicit AudioDeviceBuffer(TaskQueueFactory* task_queue_factory); 81 virtual ~AudioDeviceBuffer(); 82 83 int32_t RegisterAudioCallback(AudioTransport* audio_callback); 84 85 void StartPlayout(); 86 void StartRecording(); 87 void StopPlayout(); 88 void StopRecording(); 89 90 int32_t SetRecordingSampleRate(uint32_t fsHz); 91 int32_t SetPlayoutSampleRate(uint32_t fsHz); 92 uint32_t RecordingSampleRate() const; 93 uint32_t PlayoutSampleRate() const; 94 95 int32_t SetRecordingChannels(size_t channels); 96 int32_t SetPlayoutChannels(size_t channels); 97 size_t RecordingChannels() const; 98 size_t PlayoutChannels() const; 99 100 virtual int32_t SetRecordedBuffer(const void* audio_buffer, 101 size_t samples_per_channel); 102 virtual void SetVQEData(int play_delay_ms, int rec_delay_ms); 103 virtual int32_t DeliverRecordedData(); 104 uint32_t NewMicLevel() const; 105 106 virtual int32_t RequestPlayoutData(size_t samples_per_channel); 107 virtual int32_t GetPlayoutData(void* audio_buffer); 108 109 int32_t SetTypingStatus(bool typing_status); 110 111 private: 112 // Starts/stops periodic logging of audio stats. 113 void StartPeriodicLogging(); 114 void StopPeriodicLogging(); 115 116 // Called periodically on the internal thread created by the TaskQueue. 117 // Updates some stats but dooes it on the task queue to ensure that access of 118 // members is serialized hence avoiding usage of locks. 119 // state = LOG_START => members are initialized and the timer starts. 120 // state = LOG_STOP => no logs are printed and the timer stops. 121 // state = LOG_ACTIVE => logs are printed and the timer is kept alive. 122 void LogStats(LogState state); 123 124 // Updates counters in each play/record callback. These counters are later 125 // (periodically) read by LogStats() using a lock. 126 void UpdateRecStats(int16_t max_abs, size_t samples_per_channel); 127 void UpdatePlayStats(int16_t max_abs, size_t samples_per_channel); 128 129 // Clears all members tracking stats for recording and playout. 130 // These methods both run on the task queue. 131 void ResetRecStats(); 132 void ResetPlayStats(); 133 134 // This object lives on the main (creating) thread and most methods are 135 // called on that same thread. When audio has started some methods will be 136 // called on either a native audio thread for playout or a native thread for 137 // recording. Some members are not annotated since they are "protected by 138 // design" and adding e.g. a race checker can cause failures for very few 139 // edge cases and it is IMHO not worth the risk to use them in this class. 140 // TODO(henrika): see if it is possible to refactor and annotate all members. 141 142 // Main thread on which this object is created. 143 rtc::ThreadChecker main_thread_checker_; 144 145 Mutex lock_; 146 147 // Task queue used to invoke LogStats() periodically. Tasks are executed on a 148 // worker thread but it does not necessarily have to be the same thread for 149 // each task. 150 rtc::TaskQueue task_queue_; 151 152 // Raw pointer to AudioTransport instance. Supplied to RegisterAudioCallback() 153 // and it must outlive this object. It is not possible to change this member 154 // while any media is active. It is possible to start media without calling 155 // RegisterAudioCallback() but that will lead to ignored audio callbacks in 156 // both directions where native audio will be active but no audio samples will 157 // be transported. 158 AudioTransport* audio_transport_cb_; 159 160 // Sample rate in Hertz. Accessed atomically. 161 std::atomic<uint32_t> rec_sample_rate_; 162 std::atomic<uint32_t> play_sample_rate_; 163 164 // Number of audio channels. Accessed atomically. 165 std::atomic<size_t> rec_channels_; 166 std::atomic<size_t> play_channels_; 167 168 // Keeps track of if playout/recording are active or not. A combination 169 // of these states are used to determine when to start and stop the timer. 170 // Only used on the creating thread and not used to control any media flow. 171 bool playing_ RTC_GUARDED_BY(main_thread_checker_); 172 bool recording_ RTC_GUARDED_BY(main_thread_checker_); 173 174 // Buffer used for audio samples to be played out. Size can be changed 175 // dynamically. The 16-bit samples are interleaved, hence the size is 176 // proportional to the number of channels. 177 rtc::BufferT<int16_t> play_buffer_; 178 179 // Byte buffer used for recorded audio samples. Size can be changed 180 // dynamically. 181 rtc::BufferT<int16_t> rec_buffer_; 182 183 // Contains true of a key-press has been detected. 184 bool typing_status_; 185 186 // Delay values used by the AEC. 187 int play_delay_ms_; 188 int rec_delay_ms_; 189 190 // Counts number of times LogStats() has been called. 191 size_t num_stat_reports_ RTC_GUARDED_BY(task_queue_); 192 193 // Time stamp of last timer task (drives logging). 194 int64_t last_timer_task_time_ RTC_GUARDED_BY(task_queue_); 195 196 // Counts number of audio callbacks modulo 50 to create a signal when 197 // a new storage of audio stats shall be done. 198 int16_t rec_stat_count_; 199 int16_t play_stat_count_; 200 201 // Time stamps of when playout and recording starts. 202 int64_t play_start_time_ RTC_GUARDED_BY(main_thread_checker_); 203 int64_t rec_start_time_ RTC_GUARDED_BY(main_thread_checker_); 204 205 // Contains counters for playout and recording statistics. 206 Stats stats_ RTC_GUARDED_BY(lock_); 207 208 // Stores current stats at each timer task. Used to calculate differences 209 // between two successive timer events. 210 Stats last_stats_ RTC_GUARDED_BY(task_queue_); 211 212 // Set to true at construction and modified to false as soon as one audio- 213 // level estimate larger than zero is detected. 214 bool only_silence_recorded_; 215 216 // Set to true when logging of audio stats is enabled for the first time in 217 // StartPeriodicLogging() and set to false by StopPeriodicLogging(). 218 // Setting this member to false prevents (possiby invalid) log messages from 219 // being printed in the LogStats() task. 220 bool log_stats_ RTC_GUARDED_BY(task_queue_); 221 222 // Should *never* be defined in production builds. Only used for testing. 223 // When defined, the output signal will be replaced by a sinus tone at 440Hz. 224 #ifdef AUDIO_DEVICE_PLAYS_SINUS_TONE 225 double phase_; 226 #endif 227 }; 228 229 } // namespace webrtc 230 231 #endif // MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ 232