| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef MEDIA_AUDIO_AUDIO_SILENCE_DETECTOR_H_ | |
| 6 #define MEDIA_AUDIO_AUDIO_SILENCE_DETECTOR_H_ | |
| 7 | |
| 8 #include "base/atomic_ref_count.h" | |
| 9 #include "base/callback.h" | |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/threading/thread_checker.h" | |
| 12 #include "base/timer.h" | |
| 13 #include "media/base/media_export.h" | |
| 14 | |
| 15 // An audio silence detector. It is periodically provided an AudioBus by the | |
| 16 // native audio thread, where simple logic determines whether the audio samples | |
| 17 // in each channel in the buffer represent silence. If a long-enough period of | |
| 18 // contiguous silence is observed in all channels, a notification callback is | |
| 19 // run on the thread that constructed AudioSilenceDetector. | |
| 20 // | |
| 21 // Note that extreme care has been taken to make the | |
| 22 // AudioSilenceDetector::Scan() method safe to be called on the native audio | |
| 23 // thread. The code acquires no locks, nor engages in any operation that could | |
| 24 // result in an undetermined/unbounded amount of run-time. Comments in | |
| 25 // audio_silence_detector.cc elaborate further on the silence detection | |
| 26 // algorithm. | |
| 27 | |
| 28 namespace base { | |
| 29 class TimeDelta; | |
| 30 } | |
| 31 | |
| 32 namespace media { | |
| 33 | |
| 34 class AudioBus; | |
| 35 | |
| 36 class MEDIA_EXPORT AudioSilenceDetector { | |
| 37 public: | |
| 38 typedef base::Callback<void(bool)> AudibleCallback; | |
| 39 | |
| 40 // Tunable parameters: |questionable_silence_period| is the amount of time | |
| 41 // where audio must remain silent before triggerring a callback. | |
| 42 // |indistinguishable_silence_threshold| is the value range below which audio | |
| 43 // is considered silent, in full-scale units. | |
| 44 // | |
| 45 // TODO(miu): |indistinguishable_silence_threshold| should be specified in | |
| 46 // dbFS units rather than full-scale. We need a dbFS data type for | |
| 47 // media/audio first. | |
| 48 AudioSilenceDetector(int sample_rate, | |
| 49 const base::TimeDelta& questionable_silence_period, | |
| 50 float indistinguishable_silence_threshold); | |
| 51 | |
| 52 ~AudioSilenceDetector(); | |
| 53 | |
| 54 // Start detecting silence, notifying via the given callback. | |
| 55 void Start(const AudibleCallback& notify_is_audible); | |
| 56 | |
| 57 // Stop detecting silence. If |notify_ending_in_silence| is true, a final | |
| 58 // notify_is_audible(false) call will be made here. | |
| 59 void Stop(bool notify_ending_in_silence); | |
| 60 | |
| 61 // Scan more |frames| of audio data from |buffer|. This is usually called | |
| 62 // within the native audio thread's "more data" callback. | |
| 63 void Scan(const AudioBus* buffer, int frames); | |
| 64 | |
| 65 private: | |
| 66 // Called by |poll_timer_| at regular intervals to determine whether to invoke | |
| 67 // the callback due to a silence state change. | |
| 68 void MaybeInvokeAudibleCallback(); | |
| 69 | |
| 70 // Returns true if the first |num_frames| frames in all channels in |buffer| | |
| 71 // probably contain silence. A simple heuristic is used to quickly examine a | |
| 72 // subset of the samples in each channel, hence the name of this method. | |
| 73 // "Silence" means that the range of the sample values examined does not | |
| 74 // exceed |silence_threshold_|. | |
| 75 bool ProbablyContainsSilence(const AudioBus* buffer, int num_frames); | |
| 76 | |
| 77 // Time between polls for changes in state. | |
| 78 const base::TimeDelta polling_period_; | |
| 79 | |
| 80 // Number of frames of contiguous silence to be observed before setting | |
| 81 // |observing_silence_| to false. | |
| 82 const int frames_before_observing_silence_; | |
| 83 | |
| 84 // Threshold below which audio should be considered indistinguishably silent. | |
| 85 const float silence_threshold_; | |
| 86 | |
| 87 // Number of frames of contiguous silence observed thus far on the native | |
| 88 // audio thread. | |
| 89 int frames_silent_so_far_; | |
| 90 | |
| 91 // Boolean state (0 or 1) set by the native audio thread. This is polled | |
| 92 // regularly by the thread that invokes the callback. | |
| 93 base::AtomicRefCount observing_silence_; | |
| 94 | |
| 95 // Callback for notifying of a detected transition to silence or non-silence. | |
| 96 AudibleCallback notify_is_audible_; | |
| 97 | |
| 98 // Last reported audible state, used for de-duping callback invocations. | |
| 99 bool was_audible_; | |
| 100 | |
| 101 // Fires regularly, calling MaybeInvokeAudibleCallback(). | |
| 102 base::RepeatingTimer<AudioSilenceDetector> poll_timer_; | |
| 103 | |
| 104 // Constructor, destructor and most methods must be called on the same thread. | |
| 105 base::ThreadChecker thread_checker_; | |
| 106 | |
| 107 DISALLOW_COPY_AND_ASSIGN(AudioSilenceDetector); | |
| 108 }; | |
| 109 | |
| 110 } // namespace media | |
| 111 | |
| 112 #endif // MEDIA_AUDIO_AUDIO_SILENCE_DETECTOR_H_ | |
| OLD | NEW |