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/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 |