1 // Copyright (c) 2012 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_BASE_AUDIO_SPLICER_H_
6 #define MEDIA_BASE_AUDIO_SPLICER_H_
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/time/time.h"
11 #include "media/audio/audio_parameters.h"
12 #include "media/base/media_export.h"
13 #include "media/base/timestamp_constants.h"
19 class AudioStreamSanitizer
;
22 // Helper class that handles filling gaps and resolving overlaps.
23 class MEDIA_EXPORT AudioSplicer
{
25 AudioSplicer(int samples_per_second
,
26 const scoped_refptr
<MediaLog
>& media_log
);
30 // The number of ms to crossfade before trimming when buffers overlap.
31 kCrossfadeDurationInMilliseconds
= 5,
33 // Largest gap or overlap allowed between buffers. Anything larger than
34 // this will trigger an error. This is an arbitrary value, but the initial
35 // selection of 50ms roughly represents the duration of 2 compressed AAC or
37 kMaxTimeDeltaInMilliseconds
= 50,
40 // Resets the splicer state by clearing the output buffers queue and resetting
41 // the timestamp helper.
44 // Adds a new buffer full of samples or end of stream buffer to the splicer.
45 // Returns true if the buffer was accepted. False is returned if an error
47 bool AddInput(const scoped_refptr
<AudioBuffer
>& input
);
49 // Returns true if the splicer has a buffer to return.
50 bool HasNextBuffer() const;
52 // Removes the next buffer from the output buffer queue and returns it; this
53 // should only be called if HasNextBuffer() returns true.
54 scoped_refptr
<AudioBuffer
> GetNextBuffer();
56 // Indicates an upcoming splice point. All buffers overlapping or after the
57 // |splice_timestamp| will be considered as "before the splice." Clients must
58 // then call SetSpliceTimestamp(kNoTimestamp()) to signal that future buffers
59 // should be considered as "after the splice."
61 // Once |kCrossfadeDurationInMilliseconds| of buffers "after the splice" or
62 // end of stream has been received, the "after" buffers will be crossfaded
63 // with all "before" buffers which overlap them. "before" buffers outside
64 // of the overlap range will be discarded.
65 void SetSpliceTimestamp(base::TimeDelta splice_timestamp
);
68 friend class AudioSplicerTest
;
70 // Extracts frames to be crossfaded from |pre_splice_sanitizer_|. Transfers
71 // all frames before |splice_timestamp_| into |output_sanitizer_| and drops
72 // frames outside of the crossfade duration.
74 // The size of the returned AudioBus is the crossfade duration in frames.
75 // Crossfade duration is calculated based on the number of frames available
76 // after |splice_timestamp_| in each sanitizer and capped by
77 // |max_crossfade_duration_|.
79 // |pre_splice_sanitizer_| will be empty after this operation.
80 scoped_ptr
<AudioBus
> ExtractCrossfadeFromPreSplice(
81 scoped_refptr
<AudioBuffer
>* crossfade_buffer
);
83 // Crossfades |pre_splice_bus->frames()| frames from
84 // |post_splice_sanitizer_|
85 // with those from |pre_splice_bus|. Adds the crossfaded buffer to
86 // |output_sanitizer_| along with all buffers in |post_splice_sanitizer_|.
88 // |post_splice_sanitizer_| will be empty after this operation.
89 void CrossfadePostSplice(scoped_ptr
<AudioBus
> pre_splice_bus
,
90 const scoped_refptr
<AudioBuffer
>& crossfade_buffer
);
92 // Reset the splice and splice end timestamps.
93 void reset_splice_timestamps() {
94 splice_timestamp_
= max_splice_end_timestamp_
= kNoTimestamp();
97 const base::TimeDelta max_crossfade_duration_
;
98 base::TimeDelta splice_timestamp_
;
99 base::TimeDelta max_splice_end_timestamp_
;
101 // The various sanitizers for each stage of the crossfade process. Buffers in
102 // |output_sanitizer_| are immediately available for consumption by external
105 // Overlapped buffers go into the |pre_splice_sanitizer_| while overlapping
106 // buffers go into the |post_splice_sanitizer_|. Once enough buffers for
107 // crossfading are received the pre and post sanitizers are drained into
108 // |output_sanitizer_| by the two ExtractCrossfadeFromXXX methods above.
110 // |pre_splice_sanitizer_| is not constructed until the first splice frame is
111 // encountered. At which point it is constructed based on the timestamp state
112 // of |output_sanitizer_|. It is destructed once the splice is finished.
113 scoped_ptr
<AudioStreamSanitizer
> output_sanitizer_
;
114 scoped_ptr
<AudioStreamSanitizer
> pre_splice_sanitizer_
;
115 scoped_ptr
<AudioStreamSanitizer
> post_splice_sanitizer_
;
117 // Whether all buffers which should go into |pre_splice_sanitizer_| have been
118 // received. If true, buffers should now be put in |post_splice_sanitizer_|.
119 bool have_all_pre_splice_buffers_
;
121 DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSplicer
);