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.
5 #ifndef MEDIA_AUDIO_AUDIO_SILENCE_DETECTOR_H_
6 #define MEDIA_AUDIO_AUDIO_SILENCE_DETECTOR_H_
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"
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.
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
36 class MEDIA_EXPORT AudioSilenceDetector
{
38 typedef base::Callback
<void(bool)> AudibleCallback
;
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.
45 // TODO(miu): |indistinguishable_silence_threshold| should be specified in
46 // dbFS units rather than full-scale. We need a dbFS data type for
48 AudioSilenceDetector(int sample_rate
,
49 const base::TimeDelta
& questionable_silence_period
,
50 float indistinguishable_silence_threshold
);
52 ~AudioSilenceDetector();
54 // Start detecting silence, notifying via the given callback.
55 void Start(const AudibleCallback
& notify_is_audible
);
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
);
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
);
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();
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
);
77 // Time between polls for changes in state.
78 const base::TimeDelta polling_period_
;
80 // Number of frames of contiguous silence to be observed before setting
81 // |observing_silence_| to false.
82 const int frames_before_observing_silence_
;
84 // Threshold below which audio should be considered indistinguishably silent.
85 const float silence_threshold_
;
87 // Number of frames of contiguous silence observed thus far on the native
89 int frames_silent_so_far_
;
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_
;
95 // Callback for notifying of a detected transition to silence or non-silence.
96 AudibleCallback notify_is_audible_
;
98 // Last reported audible state, used for de-duping callback invocations.
101 // Fires regularly, calling MaybeInvokeAudibleCallback().
102 base::RepeatingTimer
<AudioSilenceDetector
> poll_timer_
;
104 // Constructor, destructor and most methods must be called on the same thread.
105 base::ThreadChecker thread_checker_
;
107 DISALLOW_COPY_AND_ASSIGN(AudioSilenceDetector
);
112 #endif // MEDIA_AUDIO_AUDIO_SILENCE_DETECTOR_H_