Bug 1839170 - Refactor Snap pulling, Add Firefox Snap Core22 and GNOME 42 SDK symbols...
[gecko.git] / dom / media / AudibilityMonitor.h
blob3206262eab37df7573577fdab7fb934bdb48937f
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef DOM_MEDIA_AUDIBILITYMONITOR_H_
8 #define DOM_MEDIA_AUDIBILITYMONITOR_H_
10 #include <cstdint>
12 #include "AudioSampleFormat.h"
13 #include "WebAudioUtils.h"
14 #include "AudioBlock.h"
15 #include "MediaData.h"
17 namespace mozilla {
19 class AudibilityMonitor {
20 public:
21 // ≈ 20 * log10(pow(2, 12)), noise floor of 12bit audio
22 const float AUDIBILITY_THRESHOLD =
23 dom::WebAudioUtils::ConvertDecibelsToLinear(-72.);
25 AudibilityMonitor(uint32_t aSamplerate, float aSilenceDurationSeconds)
26 : mSamplerate(aSamplerate),
27 mSilenceDurationSeconds(aSilenceDurationSeconds),
28 mSilentFramesInARow(0),
29 mEverAudible(false) {}
31 void Process(const AudioData* aData) {
32 ProcessInterleaved(aData->Data(), aData->mChannels);
35 void Process(const AudioBlock& aData) {
36 if (aData.IsNull() || aData.IsMuted()) {
37 mSilentFramesInARow += aData.GetDuration();
38 return;
40 ProcessPlanar(aData.ChannelData<float>(), aData.GetDuration());
43 void ProcessPlanar(const nsTArray<const float*>& aPlanar, TrackTime aFrames) {
44 uint32_t lastFrameAudibleAcrossChannels = 0;
45 for (uint32_t channel = 0; channel < aPlanar.Length(); channel++) {
46 uint32_t lastSampleAudible = 0;
47 for (uint32_t frame = 0; frame < aFrames; frame++) {
48 if (std::fabs(aPlanar[channel][frame]) > AUDIBILITY_THRESHOLD) {
49 mEverAudible = true;
50 mSilentFramesInARow = 0;
51 lastSampleAudible = frame;
54 lastFrameAudibleAcrossChannels =
55 std::max(lastFrameAudibleAcrossChannels, lastSampleAudible);
57 mSilentFramesInARow += aFrames - lastFrameAudibleAcrossChannels - 1;
60 void ProcessInterleaved(const Span<AudioDataValue>& aInterleaved,
61 size_t aChannels) {
62 MOZ_ASSERT(aInterleaved.Length() % aChannels == 0);
63 uint32_t frameCount = aInterleaved.Length() / aChannels;
64 AudioDataValue* samples = aInterleaved.Elements();
66 uint32_t readIndex = 0;
67 for (uint32_t i = 0; i < frameCount; i++) {
68 bool atLeastOneAudible = false;
69 for (uint32_t j = 0; j < aChannels; j++) {
70 if (std::fabs(AudioSampleToFloat(samples[readIndex++])) >
71 AUDIBILITY_THRESHOLD) {
72 atLeastOneAudible = true;
75 if (atLeastOneAudible) {
76 mSilentFramesInARow = 0;
77 mEverAudible = true;
78 } else {
79 mSilentFramesInARow++;
84 // A stream is considered audible if there was audible content in the last
85 // `mSilenceDurationSeconds` seconds, or it has never been audible for now.
86 bool RecentlyAudible() {
87 return mEverAudible && (static_cast<float>(mSilentFramesInARow) /
88 mSamplerate) < mSilenceDurationSeconds;
91 private:
92 const uint32_t mSamplerate;
93 const float mSilenceDurationSeconds;
94 uint64_t mSilentFramesInARow;
95 bool mEverAudible;
98 }; // namespace mozilla
100 #endif // DOM_MEDIA_AUDIBILITYMONITOR_H_