Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 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 API_AUDIO_AUDIO_FRAME_H_ |
| 12 | #define API_AUDIO_AUDIO_FRAME_H_ |
| 13 | |
Fredrik Solenberg | bbf21a3 | 2018-04-12 22:44:09 +0200 | [diff] [blame] | 14 | #include <stddef.h> |
Niels Möller | a12c42a | 2018-07-25 16:05:48 +0200 | [diff] [blame] | 15 | #include <stdint.h> |
Fredrik Solenberg | bbf21a3 | 2018-04-12 22:44:09 +0200 | [diff] [blame] | 16 | |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 17 | #include "rtc_base/constructormagic.h" |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 18 | |
| 19 | namespace webrtc { |
| 20 | |
henrika | 2a49065 | 2018-08-28 15:52:10 +0200 | [diff] [blame^] | 21 | /* This class holds up to 120 ms of super-wideband (32 kHz) stereo audio. It |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 22 | * allows for adding and subtracting frames while keeping track of the resulting |
| 23 | * states. |
| 24 | * |
| 25 | * Notes |
| 26 | * - This is a de-facto api, not designed for external use. The AudioFrame class |
| 27 | * is in need of overhaul or even replacement, and anyone depending on it |
| 28 | * should be prepared for that. |
| 29 | * - The total number of samples is samples_per_channel_ * num_channels_. |
| 30 | * - Stereo data is interleaved starting with the left channel. |
| 31 | */ |
| 32 | class AudioFrame { |
| 33 | public: |
| 34 | // Using constexpr here causes linker errors unless the variable also has an |
| 35 | // out-of-class definition, which is impractical in this header-only class. |
| 36 | // (This makes no sense because it compiles as an enum value, which we most |
| 37 | // certainly cannot take the address of, just fine.) C++17 introduces inline |
| 38 | // variables which should allow us to switch to constexpr and keep this a |
| 39 | // header-only class. |
| 40 | enum : size_t { |
henrika | 2a49065 | 2018-08-28 15:52:10 +0200 | [diff] [blame^] | 41 | // Stereo, 32 kHz, 120 ms (2 * 32 * 120) |
| 42 | // Stereo, 192 kHz, 20 ms (2 * 192 * 20) |
| 43 | kMaxDataSizeSamples = 7680, |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 44 | kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t), |
| 45 | }; |
| 46 | |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 47 | enum VADActivity { kVadActive = 0, kVadPassive = 1, kVadUnknown = 2 }; |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 48 | enum SpeechType { |
| 49 | kNormalSpeech = 0, |
| 50 | kPLC = 1, |
| 51 | kCNG = 2, |
| 52 | kPLCCNG = 3, |
| 53 | kUndefined = 4 |
| 54 | }; |
| 55 | |
| 56 | AudioFrame(); |
| 57 | |
| 58 | // Resets all members to their default state. |
| 59 | void Reset(); |
| 60 | // Same as Reset(), but leaves mute state unchanged. Muting a frame requires |
| 61 | // the buffer to be zeroed on the next call to mutable_data(). Callers |
| 62 | // intending to write to the buffer immediately after Reset() can instead use |
| 63 | // ResetWithoutMuting() to skip this wasteful zeroing. |
| 64 | void ResetWithoutMuting(); |
| 65 | |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 66 | void UpdateFrame(uint32_t timestamp, |
| 67 | const int16_t* data, |
| 68 | size_t samples_per_channel, |
| 69 | int sample_rate_hz, |
| 70 | SpeechType speech_type, |
| 71 | VADActivity vad_activity, |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 72 | size_t num_channels = 1); |
| 73 | |
| 74 | void CopyFrom(const AudioFrame& src); |
| 75 | |
| 76 | // Sets a wall-time clock timestamp in milliseconds to be used for profiling |
| 77 | // of time between two points in the audio chain. |
| 78 | // Example: |
| 79 | // t0: UpdateProfileTimeStamp() |
| 80 | // t1: ElapsedProfileTimeMs() => t1 - t0 [msec] |
| 81 | void UpdateProfileTimeStamp(); |
| 82 | // Returns the time difference between now and when UpdateProfileTimeStamp() |
| 83 | // was last called. Returns -1 if UpdateProfileTimeStamp() has not yet been |
| 84 | // called. |
| 85 | int64_t ElapsedProfileTimeMs() const; |
| 86 | |
| 87 | // data() returns a zeroed static buffer if the frame is muted. |
| 88 | // mutable_frame() always returns a non-static buffer; the first call to |
| 89 | // mutable_frame() zeros the non-static buffer and marks the frame unmuted. |
| 90 | const int16_t* data() const; |
| 91 | int16_t* mutable_data(); |
| 92 | |
| 93 | // Prefer to mute frames using AudioFrameOperations::Mute. |
| 94 | void Mute(); |
| 95 | // Frame is muted by default. |
| 96 | bool muted() const; |
| 97 | |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 98 | // RTP timestamp of the first sample in the AudioFrame. |
| 99 | uint32_t timestamp_ = 0; |
| 100 | // Time since the first frame in milliseconds. |
| 101 | // -1 represents an uninitialized value. |
| 102 | int64_t elapsed_time_ms_ = -1; |
| 103 | // NTP time of the estimated capture time in local timebase in milliseconds. |
| 104 | // -1 represents an uninitialized value. |
| 105 | int64_t ntp_time_ms_ = -1; |
| 106 | size_t samples_per_channel_ = 0; |
| 107 | int sample_rate_hz_ = 0; |
| 108 | size_t num_channels_ = 0; |
| 109 | SpeechType speech_type_ = kUndefined; |
| 110 | VADActivity vad_activity_ = kVadUnknown; |
| 111 | // Monotonically increasing timestamp intended for profiling of audio frames. |
| 112 | // Typically used for measuring elapsed time between two different points in |
| 113 | // the audio path. No lock is used to save resources and we are thread safe |
Danil Chapovalov | 0bc58cf | 2018-06-21 13:32:56 +0200 | [diff] [blame] | 114 | // by design. Also, absl::optional is not used since it will cause a "complex |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 115 | // class/struct needs an explicit out-of-line destructor" build error. |
| 116 | int64_t profile_timestamp_ms_ = 0; |
| 117 | |
| 118 | private: |
| 119 | // A permamently zeroed out buffer to represent muted frames. This is a |
| 120 | // header-only class, so the only way to avoid creating a separate empty |
| 121 | // buffer per translation unit is to wrap a static in an inline function. |
| 122 | static const int16_t* empty_data(); |
| 123 | |
| 124 | int16_t data_[kMaxDataSizeSamples]; |
| 125 | bool muted_ = true; |
| 126 | |
| 127 | RTC_DISALLOW_COPY_AND_ASSIGN(AudioFrame); |
| 128 | }; |
| 129 | |
| 130 | } // namespace webrtc |
| 131 | |
| 132 | #endif // API_AUDIO_AUDIO_FRAME_H_ |