1 // Copyright (c) 2014 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.
9 #include "media/base/audio_bus.h"
10 #include "media/base/audio_shifter.h"
14 // return true if x is between a and b.
15 static bool between(double x
, double a
, double b
) {
17 return b
<= x
&& x
<= a
;
18 return a
<= x
&& x
<= b
;
23 explicit ClockSmoother(base::TimeDelta clock_accuracy
) :
24 clock_accuracy_(clock_accuracy
),
25 inaccuracy_delta_(clock_accuracy
* 10) {
26 inaccuracies_
.push_back(std::make_pair(inaccuracy_sum_
, inaccuracy_delta_
));
29 base::TimeTicks
Smooth(base::TimeTicks t
,
30 base::TimeDelta delta
) {
31 base::TimeTicks ret
= t
;
32 if (!previous_
.is_null()) {
33 base::TimeDelta actual_delta
= t
- previous_
;
34 base::TimeDelta new_fraction_off
= actual_delta
- delta
;
35 inaccuracy_sum_
+= new_fraction_off
;
36 inaccuracy_delta_
+= actual_delta
;
37 inaccuracies_
.push_back(std::make_pair(new_fraction_off
, actual_delta
));
38 if (inaccuracies_
.size() > 1000) {
39 inaccuracy_sum_
-= inaccuracies_
.front().first
;
40 inaccuracy_delta_
-= inaccuracies_
.front().second
;
41 inaccuracies_
.pop_front();
43 // 0.01 means 1% faster than regular clock.
44 // -0.02 means 2% slower than regular clock.
45 double fraction_off
= inaccuracy_sum_
.InSecondsF() /
46 inaccuracy_delta_
.InSecondsF();
48 double delta_seconds
= delta
.InSecondsF();
49 delta_seconds
+= delta_seconds
* fraction_off
;
50 base::TimeTicks expected
= previous_
+
51 base::TimeDelta::FromSecondsD(delta_seconds
);
52 base::TimeDelta diff
= t
- expected
;
53 if (diff
< clock_accuracy_
&& diff
> -clock_accuracy_
) {
54 ret
= t
+ diff
/ 1000;
61 // 1.01 means 1% faster than regular clock.
62 // -0.98 means 2% slower than regular clock.
64 return 1.0 + inaccuracy_sum_
.InSecondsF() /
65 inaccuracy_delta_
.InSecondsF();
69 base::TimeDelta clock_accuracy_
;
70 std::deque
<std::pair
<base::TimeDelta
, base::TimeDelta
> > inaccuracies_
;
71 base::TimeDelta inaccuracy_sum_
;
72 base::TimeDelta inaccuracy_delta_
;
73 base::TimeTicks previous_
;
76 AudioShifter::AudioQueueEntry::AudioQueueEntry(
77 base::TimeTicks target_playout_time_
,
78 scoped_ptr
<AudioBus
> audio_
) :
79 target_playout_time(target_playout_time_
),
80 audio(audio_
.release()) {
83 AudioShifter::AudioQueueEntry::~AudioQueueEntry() {}
85 AudioShifter::AudioShifter(base::TimeDelta max_buffer_size
,
86 base::TimeDelta clock_accuracy
,
87 base::TimeDelta adjustment_time
,
90 max_buffer_size_(max_buffer_size
),
91 clock_accuracy_(clock_accuracy
),
92 adjustment_time_(adjustment_time
),
94 input_clock_smoother_(new ClockSmoother(clock_accuracy
)),
95 output_clock_smoother_(new ClockSmoother(clock_accuracy
)),
98 previous_requested_samples_(0),
99 resampler_(channels
, 1.0, 96,
100 base::Bind(&AudioShifter::ResamplerCallback
,
101 base::Unretained(this))),
102 current_ratio_(1.0) {
105 AudioShifter::~AudioShifter() {}
107 void AudioShifter::Push(scoped_ptr
<AudioBus
> input
,
108 base::TimeTicks playout_time
) {
109 if (!queue_
.empty()) {
110 playout_time
= input_clock_smoother_
->Smooth(
112 base::TimeDelta::FromSeconds(queue_
.back().audio
->frames()) / rate_
);
114 queue_
.push_back(AudioQueueEntry(playout_time
, input
.Pass()));
115 while (!queue_
.empty() &&
116 queue_
.back().target_playout_time
-
117 queue_
.front().target_playout_time
> max_buffer_size_
) {
118 DVLOG(1) << "AudioShifter: Audio overflow!";
124 void AudioShifter::Pull(AudioBus
* output
,
125 base::TimeTicks playout_time
) {
126 // Add the kernel size since we incur some internal delay in
127 // resampling. All resamplers incur some delay, and for the
128 // SincResampler (used by MultiChannelResampler), this is
129 // (currently) kKernalSize / 2 frames.
130 playout_time
+= base::TimeDelta::FromSeconds(
131 SincResampler::kKernelSize
) / rate_
/ 2;
132 playout_time
= output_clock_smoother_
->Smooth(
134 base::TimeDelta::FromSeconds(previous_requested_samples_
) / rate_
);
135 previous_requested_samples_
= output
->frames();
137 base::TimeTicks stream_time
;
138 base::TimeTicks buffer_end_time
;
139 if (queue_
.empty()) {
140 DCHECK_EQ(position_
, 0UL);
141 stream_time
= end_of_last_consumed_audiobus_
;
142 buffer_end_time
= end_of_last_consumed_audiobus_
;
144 stream_time
= queue_
.front().target_playout_time
;
145 buffer_end_time
= queue_
.back().target_playout_time
;
147 stream_time
+= base::TimeDelta::FromSecondsD(
148 (position_
- resampler_
.BufferedFrames()) / rate_
);
151 base::TimeDelta::FromSeconds(output
->frames() * 2) / rate_
+
152 clock_accuracy_
> buffer_end_time
- stream_time
) {
153 // We're not running right now, and we don't really have enough data
154 // to satisfy output reliably. Wait.
158 if (playout_time
< stream_time
-
159 base::TimeDelta::FromSeconds(output
->frames()) / rate_
/ 2 -
160 (running_
? clock_accuracy_
: base::TimeDelta())) {
161 // |playout_time| is too far before the earliest known audio sample.
166 if (buffer_end_time
< playout_time
) {
167 // If the "playout_time" is actually capture time, then
168 // the entire queue will be in the past. Since we cannot
169 // play audio in the past. We add one buffer size to the
170 // bias to avoid buffer underruns in the future.
171 if (bias_
== base::TimeDelta()) {
172 bias_
= playout_time
- stream_time
+
174 base::TimeDelta::FromSeconds(output
->frames()) / rate_
;
176 stream_time
+= bias_
;
178 // Normal case, some part of the queue is
179 // ahead of the scheduled playout time.
181 // Skip any data that is simply too old, if we have
182 // better data somewhere in the qeueue.
185 bias_
= base::TimeDelta();
187 while (!queue_
.empty() &&
188 playout_time
- stream_time
> clock_accuracy_
) {
192 if (queue_
.empty()) {
196 stream_time
= queue_
.front().target_playout_time
;
201 double steady_ratio
= output_clock_smoother_
->Rate() /
202 input_clock_smoother_
->Rate();
203 double time_difference
= (playout_time
- stream_time
).InSecondsF();
204 double adjustment_time
= adjustment_time_
.InSecondsF();
205 // This is the ratio we would need to get perfect sync after
206 // |adjustment_time| has passed.
207 double slow_ratio
= steady_ratio
+ time_difference
/ adjustment_time
;
208 slow_ratio
= std::max(0.9, std::min(1.1, slow_ratio
));
209 adjustment_time
= output
->frames() / static_cast<double>(rate_
);
210 // This is ratio we we'd need get perfect sync at the end of the
211 // current output audiobus.
212 double fast_ratio
= steady_ratio
+ time_difference
/ adjustment_time
;
213 fast_ratio
= std::max(0.9, std::min(1.1, fast_ratio
));
215 // If the current ratio is somewhere between the slow and the fast
216 // ratio, then keep it. This means we don't have to recalculate the
217 // tables very often and also allows us to converge on good sync faster.
218 if (!between(current_ratio_
, slow_ratio
, fast_ratio
)) {
219 // Check if the direction has changed.
220 if ((current_ratio_
< steady_ratio
) == (slow_ratio
< steady_ratio
)) {
221 // Two possible scenarios:
222 // Either we're really close to perfect sync, but the current ratio
223 // would overshoot, or the current ratio is insufficient to get to
224 // perfect sync in the alloted time. Clamp.
225 double max_ratio
= std::max(fast_ratio
, slow_ratio
);
226 double min_ratio
= std::min(fast_ratio
, slow_ratio
);
227 current_ratio_
= std::min(max_ratio
,
228 std::max(min_ratio
, current_ratio_
));
230 // The "direction" has changed. (From speed up to slow down or
231 // vice versa, so we just take the slow ratio.
232 current_ratio_
= slow_ratio
;
234 resampler_
.SetRatio(current_ratio_
);
236 resampler_
.Resample(output
->frames(), output
);
239 void AudioShifter::ResamplerCallback(int frame_delay
, AudioBus
* destination
) {
240 // TODO(hubbe): Use frame_delay
242 while (pos
< destination
->frames() && !queue_
.empty()) {
243 size_t to_copy
= std::min
<size_t>(
244 queue_
.front().audio
->frames() - position_
,
245 destination
->frames() - pos
);
246 CHECK_GT(to_copy
, 0UL);
247 queue_
.front().audio
->CopyPartialFramesTo(position_
,
252 position_
+= to_copy
;
253 if (position_
>= static_cast<size_t>(queue_
.front().audio
->frames())) {
254 end_of_last_consumed_audiobus_
= queue_
.front().target_playout_time
+
255 base::TimeDelta::FromSeconds(queue_
.front().audio
->frames()) / rate_
;
256 position_
-= queue_
.front().audio
->frames();
261 if (pos
< destination
->frames()) {
265 previous_playout_time_
= base::TimeTicks();
266 bias_
= base::TimeDelta();
267 destination
->ZeroFramesPartial(pos
, destination
->frames() - pos
);
271 void AudioShifter::Flush() {
276 previous_playout_time_
= base::TimeTicks();
277 bias_
= base::TimeDelta();
280 void AudioShifter::Zero(AudioBus
* output
) {
283 previous_playout_time_
= base::TimeTicks();
284 bias_
= base::TimeDelta();