Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(820)

Unified Diff: media/base/audio_splicer_unittest.cc

Issue 156783003: Enhance AudioSplicer to crossfade marked splice frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixes. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/audio_splicer_unittest.cc
diff --git a/media/base/audio_splicer_unittest.cc b/media/base/audio_splicer_unittest.cc
index 43902687fae9f3bcc55824647581be817c3795b6..43af22d1e33a2acd4a6b4fce6dff1bd04cd61650 100644
--- a/media/base/audio_splicer_unittest.cc
+++ b/media/base/audio_splicer_unittest.cc
@@ -22,8 +22,10 @@ class AudioSplicerTest : public ::testing::Test {
public:
AudioSplicerTest()
: splicer_(kDefaultSampleRate),
- input_timestamp_helper_(kDefaultSampleRate) {
+ input_timestamp_helper_(kDefaultSampleRate),
+ output_timestamp_helper_(kDefaultSampleRate) {
input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta());
+ output_timestamp_helper_.SetBaseTimestamp(base::TimeDelta());
}
scoped_refptr<AudioBuffer> GetNextInputBuffer(float value) {
@@ -43,20 +45,123 @@ class AudioSplicerTest : public ::testing::Test {
return buffer;
}
- bool VerifyData(scoped_refptr<AudioBuffer> buffer, float value) {
+ bool VerifyData(const scoped_refptr<AudioBuffer>& buffer, float value) {
int frames = buffer->frame_count();
scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames);
buffer->ReadFrames(frames, 0, 0, bus.get());
- for (int i = 0; i < frames; ++i) {
- if (bus->channel(0)[i] != value)
- return false;
+ for (int ch = 0; ch < buffer->channel_count(); ++ch) {
+ for (int i = 0; i < frames; ++i) {
+ if (bus->channel(ch)[i] != value)
+ return false;
+ }
}
return true;
}
+ void VerifyNextBuffer(const scoped_refptr<AudioBuffer>& input, float value) {
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<AudioBuffer> output = splicer_.GetNextBuffer();
+ EXPECT_EQ(input->timestamp(), output->timestamp());
+ EXPECT_EQ(input->duration(), output->duration());
+ EXPECT_EQ(input->frame_count(), output->frame_count());
+ EXPECT_TRUE(VerifyData(output, value));
+ output_timestamp_helper_.AddFrames(output->frame_count());
+ }
+
+ void VerifyPreSpliceOutput(
+ const scoped_refptr<AudioBuffer>& overlapped_buffer,
+ const scoped_refptr<AudioBuffer>& overlapping_buffer,
+ float overlapped_value) {
+ const base::TimeDelta kSpliceTimestamp = overlapping_buffer->timestamp();
+ const int kExpectedPreSpliceSize =
+ output_timestamp_helper_.GetFramesToTarget(kSpliceTimestamp);
+ const base::TimeDelta kExpectedPreSpliceDuration =
+ output_timestamp_helper_.GetFrameDuration(kExpectedPreSpliceSize);
+
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<AudioBuffer> pre_splice_output = splicer_.GetNextBuffer();
+ EXPECT_EQ(overlapped_buffer->timestamp(), pre_splice_output->timestamp());
+ EXPECT_EQ(kExpectedPreSpliceDuration, pre_splice_output->duration());
+ EXPECT_EQ(kExpectedPreSpliceSize, pre_splice_output->frame_count());
+ EXPECT_TRUE(VerifyData(pre_splice_output, overlapped_value));
+ output_timestamp_helper_.AddFrames(pre_splice_output->frame_count());
+ }
+
+ base::TimeDelta CalculateCrossfadeDuration(
+ const scoped_refptr<AudioBuffer>& overlapped_buffer,
+ const scoped_refptr<AudioBuffer>& overlapping_buffer) {
+ return std::min(max_crossfade_duration(),
+ std::min(overlapped_buffer->timestamp() +
+ overlapped_buffer->duration() -
+ overlapping_buffer->timestamp(),
+ overlapping_buffer->duration()));
+ }
+
+ void VerifyCrossfadeOutput(
+ const scoped_refptr<AudioBuffer>& overlapped_buffer,
+ const scoped_refptr<AudioBuffer>& overlapping_buffer,
+ float overlapped_value,
+ float overlapping_value,
+ base::TimeDelta* expected_crossfade_duration,
+ int64* expected_crossfade_size) {
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+
+ const base::TimeDelta kSpliceTimestamp =
acolwell GONE FROM CHROMIUM 2014/02/27 17:10:14 I'm a little concerned that we are trying to repli
DaleCurtis 2014/02/27 19:45:01 I generally dislike constant only verification in
DaleCurtis 2014/02/28 00:24:41 Mostly done. I also cleaned up the verify syntax.
+ output_timestamp_helper_.GetTimestamp();
+ *expected_crossfade_size = output_timestamp_helper_.GetFramesToTarget(
+ kSpliceTimestamp +
+ CalculateCrossfadeDuration(overlapped_buffer, overlapping_buffer));
+ // Don't use the calculated duration directly as it may differ in truthiness
+ // by a few microseconds from what the AudioTimestampHelper is returning.
+ *expected_crossfade_duration =
+ output_timestamp_helper_.GetFrameDuration(*expected_crossfade_size);
+
+ scoped_refptr<AudioBuffer> crossfade_output = splicer_.GetNextBuffer();
+ EXPECT_EQ(kSpliceTimestamp, crossfade_output->timestamp());
+ EXPECT_EQ(*expected_crossfade_duration, crossfade_output->duration());
+ EXPECT_EQ(*expected_crossfade_size, crossfade_output->frame_count());
+ output_timestamp_helper_.AddFrames(crossfade_output->frame_count());
+
+ // Verify the actual crossfade.
+ const int frames = crossfade_output->frame_count();
+ scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames);
+ crossfade_output->ReadFrames(frames, 0, 0, bus.get());
+ for (int ch = 0; ch < crossfade_output->channel_count(); ++ch) {
+ float cf_ratio = 0;
+ const float cf_increment = 1.0f / frames;
+ for (int i = 0; i < frames; ++i, cf_ratio += cf_increment) {
+ const float actual = bus->channel(ch)[i];
+ const float expected =
+ (1.0f - cf_ratio) * overlapped_value + cf_ratio * overlapping_value;
+ ASSERT_FLOAT_EQ(expected, actual) << "i=" << i;
+ }
+ }
+ }
+
+ bool AddInput(const scoped_refptr<AudioBuffer>& input) {
+ // Since the splicer doesn't make copies it's working directly on the input
+ // buffers. We must make a copy before adding to ensure the original buffer
+ // is not modified in unexpected ways.
+ scoped_refptr<AudioBuffer> buffer_copy =
+ input->end_of_stream()
+ ? AudioBuffer::CreateEOSBuffer()
+ : AudioBuffer::CopyFrom(kSampleFormat,
+ input->channel_count(),
+ input->frame_count(),
+ &input->channel_data()[0],
+ input->timestamp(),
+ input->duration());
+ return splicer_.AddInput(buffer_copy);
+ }
+
+ base::TimeDelta max_crossfade_duration() {
+ return splicer_.max_crossfade_duration_;
+ }
+
protected:
AudioSplicer splicer_;
AudioTimestampHelper input_timestamp_helper_;
+ AudioTimestampHelper output_timestamp_helper_;
DISALLOW_COPY_AND_ASSIGN(AudioSplicerTest);
};
@@ -66,40 +171,24 @@ TEST_F(AudioSplicerTest, PassThru) {
// Test single buffer pass-thru behavior.
scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_TRUE(splicer_.HasNextBuffer());
-
- scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer();
+ EXPECT_TRUE(AddInput(input_1));
+ VerifyNextBuffer(input_1, 0.1f);
EXPECT_FALSE(splicer_.HasNextBuffer());
- EXPECT_EQ(input_1->timestamp(), output_1->timestamp());
- EXPECT_EQ(input_1->duration(), output_1->duration());
- EXPECT_EQ(input_1->frame_count(), output_1->frame_count());
- EXPECT_TRUE(VerifyData(output_1, 0.1f));
// Test that multiple buffers can be queued in the splicer.
scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
- EXPECT_TRUE(splicer_.AddInput(input_2));
- EXPECT_TRUE(splicer_.AddInput(input_3));
- EXPECT_TRUE(splicer_.HasNextBuffer());
-
- scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
- EXPECT_TRUE(splicer_.HasNextBuffer());
- EXPECT_EQ(input_2->timestamp(), output_2->timestamp());
- EXPECT_EQ(input_2->duration(), output_2->duration());
- EXPECT_EQ(input_2->frame_count(), output_2->frame_count());
-
- scoped_refptr<AudioBuffer> output_3 = splicer_.GetNextBuffer();
+ EXPECT_TRUE(AddInput(input_2));
+ EXPECT_TRUE(AddInput(input_3));
+ VerifyNextBuffer(input_2, 0.2f);
+ VerifyNextBuffer(input_3, 0.3f);
EXPECT_FALSE(splicer_.HasNextBuffer());
- EXPECT_EQ(input_3->timestamp(), output_3->timestamp());
- EXPECT_EQ(input_3->duration(), output_3->duration());
- EXPECT_EQ(input_3->frame_count(), output_3->frame_count());
}
TEST_F(AudioSplicerTest, Reset) {
scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_TRUE(splicer_.HasNextBuffer());
+ EXPECT_TRUE(AddInput(input_1));
+ ASSERT_TRUE(splicer_.HasNextBuffer());
splicer_.Reset();
EXPECT_FALSE(splicer_.HasNextBuffer());
@@ -112,14 +201,10 @@ TEST_F(AudioSplicerTest, Reset) {
// Verify that a new input buffer passes through as expected.
scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
- EXPECT_TRUE(splicer_.AddInput(input_2));
- EXPECT_TRUE(splicer_.HasNextBuffer());
-
- scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_TRUE(AddInput(input_2));
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+ VerifyNextBuffer(input_2, 0.2f);
EXPECT_FALSE(splicer_.HasNextBuffer());
- EXPECT_EQ(input_2->timestamp(), output_2->timestamp());
- EXPECT_EQ(input_2->duration(), output_2->duration());
- EXPECT_EQ(input_2->frame_count(), output_2->frame_count());
}
TEST_F(AudioSplicerTest, EndOfStream) {
@@ -128,30 +213,22 @@ TEST_F(AudioSplicerTest, EndOfStream) {
scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.2f);
EXPECT_TRUE(input_2->end_of_stream());
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_TRUE(splicer_.AddInput(input_2));
- EXPECT_TRUE(splicer_.HasNextBuffer());
+ EXPECT_TRUE(AddInput(input_1));
+ EXPECT_TRUE(AddInput(input_2));
+
+ VerifyNextBuffer(input_1, 0.1f);
- scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer();
scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
EXPECT_FALSE(splicer_.HasNextBuffer());
- EXPECT_EQ(input_1->timestamp(), output_1->timestamp());
- EXPECT_EQ(input_1->duration(), output_1->duration());
- EXPECT_EQ(input_1->frame_count(), output_1->frame_count());
-
EXPECT_TRUE(output_2->end_of_stream());
// Verify that buffers can be added again after Reset().
splicer_.Reset();
- EXPECT_TRUE(splicer_.AddInput(input_3));
- scoped_refptr<AudioBuffer> output_3 = splicer_.GetNextBuffer();
+ EXPECT_TRUE(AddInput(input_3));
+ VerifyNextBuffer(input_3, 0.2f);
EXPECT_FALSE(splicer_.HasNextBuffer());
- EXPECT_EQ(input_3->timestamp(), output_3->timestamp());
- EXPECT_EQ(input_3->duration(), output_3->duration());
- EXPECT_EQ(input_3->frame_count(), output_3->frame_count());
}
-
// Test the gap insertion code.
// +--------------+ +--------------+
// |11111111111111| |22222222222222|
@@ -170,23 +247,14 @@ TEST_F(AudioSplicerTest, GapInsertion) {
input_timestamp_helper_.AddFrames(kGapSize);
scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_TRUE(splicer_.AddInput(input_2));
-
- // Verify that a gap buffer is generated.
- EXPECT_TRUE(splicer_.HasNextBuffer());
- scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer();
- scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
- scoped_refptr<AudioBuffer> output_3 = splicer_.GetNextBuffer();
- EXPECT_FALSE(splicer_.HasNextBuffer());
+ EXPECT_TRUE(AddInput(input_1));
+ EXPECT_TRUE(AddInput(input_2));
// Verify that the first input buffer passed through unmodified.
- EXPECT_EQ(input_1->timestamp(), output_1->timestamp());
- EXPECT_EQ(input_1->duration(), output_1->duration());
- EXPECT_EQ(input_1->frame_count(), output_1->frame_count());
- EXPECT_TRUE(VerifyData(output_1, 0.1f));
+ VerifyNextBuffer(input_1, 0.1f);
// Verify the contents of the gap buffer.
+ scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
base::TimeDelta gap_timestamp =
input_1->timestamp() + input_1->duration();
base::TimeDelta gap_duration = input_2->timestamp() - gap_timestamp;
@@ -197,13 +265,10 @@ TEST_F(AudioSplicerTest, GapInsertion) {
EXPECT_TRUE(VerifyData(output_2, 0.0f));
// Verify that the second input buffer passed through unmodified.
- EXPECT_EQ(input_2->timestamp(), output_3->timestamp());
- EXPECT_EQ(input_2->duration(), output_3->duration());
- EXPECT_EQ(input_2->frame_count(), output_3->frame_count());
- EXPECT_TRUE(VerifyData(output_3, 0.2f));
+ VerifyNextBuffer(input_2, 0.2f);
+ EXPECT_FALSE(splicer_.HasNextBuffer());
}
-
// Test that an error is signalled when the gap between input buffers is
// too large.
TEST_F(AudioSplicerTest, GapTooLarge) {
@@ -215,17 +280,10 @@ TEST_F(AudioSplicerTest, GapTooLarge) {
input_timestamp_helper_.AddFrames(kGapSize);
scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_FALSE(splicer_.AddInput(input_2));
-
- EXPECT_TRUE(splicer_.HasNextBuffer());
- scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer();
+ EXPECT_TRUE(AddInput(input_1));
+ EXPECT_FALSE(AddInput(input_2));
- // Verify that the first input buffer passed through unmodified.
- EXPECT_EQ(input_1->timestamp(), output_1->timestamp());
- EXPECT_EQ(input_1->duration(), output_1->duration());
- EXPECT_EQ(input_1->frame_count(), output_1->frame_count());
- EXPECT_TRUE(VerifyData(output_1, 0.1f));
+ VerifyNextBuffer(input_1, 0.1f);
// Verify that the second buffer is not available.
EXPECT_FALSE(splicer_.HasNextBuffer());
@@ -237,17 +295,11 @@ TEST_F(AudioSplicerTest, GapTooLarge) {
// Verify that valid buffers are still accepted.
scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
- EXPECT_TRUE(splicer_.AddInput(input_3));
- EXPECT_TRUE(splicer_.HasNextBuffer());
- scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_TRUE(AddInput(input_3));
+ VerifyNextBuffer(input_3, 0.3f);
EXPECT_FALSE(splicer_.HasNextBuffer());
- EXPECT_EQ(input_3->timestamp(), output_2->timestamp());
- EXPECT_EQ(input_3->duration(), output_2->duration());
- EXPECT_EQ(input_3->frame_count(), output_2->frame_count());
- EXPECT_TRUE(VerifyData(output_2, 0.3f));
}
-
// Verifies that an error is signalled if AddInput() is called
// with a timestamp that is earlier than the first buffer added.
TEST_F(AudioSplicerTest, BufferAddedBeforeBase) {
@@ -261,11 +313,10 @@ TEST_F(AudioSplicerTest, BufferAddedBeforeBase) {
scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.1f);
EXPECT_GT(input_1->timestamp(), input_2->timestamp());
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_FALSE(splicer_.AddInput(input_2));
+ EXPECT_TRUE(AddInput(input_1));
+ EXPECT_FALSE(AddInput(input_2));
}
-
// Test when one buffer partially overlaps another.
// +--------------+
// |11111111111111|
@@ -288,23 +339,18 @@ TEST_F(AudioSplicerTest, PartialOverlap) {
scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_TRUE(splicer_.AddInput(input_2));
+ EXPECT_TRUE(AddInput(input_1));
+ EXPECT_TRUE(AddInput(input_2));
+
+ // Verify that the first input buffer passed through unmodified.
+ VerifyNextBuffer(input_1, 0.1f);
+ ASSERT_TRUE(splicer_.HasNextBuffer());
- EXPECT_TRUE(splicer_.HasNextBuffer());
- scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer();
scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
EXPECT_FALSE(splicer_.HasNextBuffer());
- // Verify that the first input buffer passed through unmodified.
- EXPECT_EQ(input_1->timestamp(), output_1->timestamp());
- EXPECT_EQ(input_1->duration(), output_1->duration());
- EXPECT_EQ(input_1->frame_count(), output_1->frame_count());
- EXPECT_TRUE(VerifyData(output_1, 0.1f));
-
// Verify that the second input buffer was truncated to only contain
- // the samples that are after the end of |input_1|. Note that data is not
- // copied, so |input_2|'s values are modified.
+ // the samples that are after the end of |input_1|.
base::TimeDelta expected_timestamp =
input_1->timestamp() + input_1->duration();
base::TimeDelta expected_duration =
@@ -314,7 +360,6 @@ TEST_F(AudioSplicerTest, PartialOverlap) {
EXPECT_TRUE(VerifyData(output_2, 0.2f));
}
-
// Test that an input buffer that is completely overlapped by a buffer
// that was already added is dropped.
// +--------------+
@@ -348,27 +393,221 @@ TEST_F(AudioSplicerTest, DropBuffer) {
input_timestamp_helper_.AddFrames(input_1->frame_count());
scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
- EXPECT_TRUE(splicer_.AddInput(input_1));
- EXPECT_TRUE(splicer_.AddInput(input_2));
- EXPECT_TRUE(splicer_.AddInput(input_3));
+ EXPECT_TRUE(AddInput(input_1));
+ EXPECT_TRUE(AddInput(input_2));
+ EXPECT_TRUE(AddInput(input_3));
- EXPECT_TRUE(splicer_.HasNextBuffer());
- scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer();
- scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
+ VerifyNextBuffer(input_1, 0.1f);
+ VerifyNextBuffer(input_3, 0.3f);
EXPECT_FALSE(splicer_.HasNextBuffer());
+}
- // Verify that the first input buffer passed through unmodified.
- EXPECT_EQ(input_1->timestamp(), output_1->timestamp());
- EXPECT_EQ(input_1->duration(), output_1->duration());
- EXPECT_EQ(input_1->frame_count(), output_1->frame_count());
- EXPECT_TRUE(VerifyData(output_1, 0.1f));
-
- // Verify that the second output buffer only contains
- // the samples that are in |input_3|.
- EXPECT_EQ(input_3->timestamp(), output_2->timestamp());
- EXPECT_EQ(input_3->duration(), output_2->duration());
- EXPECT_EQ(input_3->frame_count(), output_2->frame_count());
- EXPECT_TRUE(VerifyData(output_2, 0.3f));
+// Test crossfade when one buffer partially overlaps another.
+// +--------------+
+// |11111111111111|
+// +--------------+
+// +--------------+
+// |22222222222222|
+// +--------------+
+// Results in:
+// +----------+----+----------+
+// |1111111111|xxxx|2222222222|
+// +----------+----+----------+
+// Where "xxxx" represents the crossfaded portion of the signal.
+TEST_F(AudioSplicerTest, PartialOverlapCrossfade) {
+ const int kCrossfadeSize =
+ input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
+ const int kBufferSize = kCrossfadeSize * 2;
+
+ scoped_refptr<AudioBuffer> extra_pre_splice_buffer =
+ GetNextInputBuffer(0.2f, kBufferSize);
+ scoped_refptr<AudioBuffer> overlapped_buffer =
+ GetNextInputBuffer(1.0f, kBufferSize);
+
+ // Reset timestamp helper so that the next buffer will have a timestamp that
+ // starts in the middle of |overlapped_buffer|.
+ input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
+ input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() -
+ kCrossfadeSize);
+ const base::TimeDelta splice_timestamp =
+ input_timestamp_helper_.GetTimestamp();
+ splicer_.SetSpliceTimestamp(splice_timestamp);
+ scoped_refptr<AudioBuffer> overlapping_buffer =
+ GetNextInputBuffer(0.0f, kBufferSize);
+
+ // |extra_pre_splice_buffer| is entirely before the splice and should be ready
+ // for output.
+ EXPECT_TRUE(AddInput(extra_pre_splice_buffer));
+ VerifyNextBuffer(extra_pre_splice_buffer, 0.2f);
+
+ // The splicer should be internally queuing input since |overlapped_buffer| is
+ // part of the splice.
+ EXPECT_TRUE(AddInput(overlapped_buffer));
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // |overlapping_buffer| should complete the splice, so ensure output is now
+ // available.
+ EXPECT_TRUE(AddInput(overlapping_buffer));
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+
+ // Add one more buffer to make sure it's passed through untouched.
+ scoped_refptr<AudioBuffer> extra_post_splice_buffer =
+ GetNextInputBuffer(0.5f, kBufferSize);
+ EXPECT_TRUE(AddInput(extra_post_splice_buffer));
+
+ VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 1.0f);
+
+ int64 expected_crossfade_size = 0;
+ base::TimeDelta expected_crossfade_duration;
+ VerifyCrossfadeOutput(overlapped_buffer,
+ overlapping_buffer,
+ 1.0f,
+ 0.0f,
+ &expected_crossfade_duration,
+ &expected_crossfade_size);
+ const int kExpectedPostSpliceSize =
+ overlapping_buffer->frame_count() - expected_crossfade_size;
+
+ // Retrieve the remaining portion after crossfade.
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
+ EXPECT_EQ(output_timestamp_helper_.GetTimestamp(),
+ post_splice_output->timestamp());
+ EXPECT_EQ(kExpectedPostSpliceSize, post_splice_output->frame_count());
+ EXPECT_EQ(output_timestamp_helper_.GetFrameDuration(kExpectedPostSpliceSize),
+ post_splice_output->duration());
+
+ EXPECT_TRUE(VerifyData(post_splice_output, 0.0f));
+
+ VerifyNextBuffer(extra_post_splice_buffer, 0.5f);
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+}
+
+// Test crossfade when one buffer partially overlaps another, but an end of
+// stream buffer is received before the crossfade duration is reached.
+// +--------------+
+// |11111111111111|
+// +--------------+
+// +---------++---+
+// |222222222||EOS|
+// +---------++---+
+// Results in:
+// +----------+----+----++---+
+// |1111111111|xxxx|2222||EOS|
+// +----------+----+----++---+
+// Where "x" represents the crossfaded portion of the signal.
+TEST_F(AudioSplicerTest, PartialOverlapCrossfadeEndOfStream) {
+ const int kCrossfadeSize =
+ input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
+
+ scoped_refptr<AudioBuffer> overlapped_buffer =
+ GetNextInputBuffer(1.0f, kCrossfadeSize * 2);
+
+ // Reset timestamp helper so that the next buffer will have a timestamp that
+ // starts 3/4 of the way into |overlapped_buffer|.
+ input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
+ input_timestamp_helper_.AddFrames(3 * overlapped_buffer->frame_count() / 4);
+ const base::TimeDelta splice_timestamp =
+ input_timestamp_helper_.GetTimestamp();
+ splicer_.SetSpliceTimestamp(splice_timestamp);
+ scoped_refptr<AudioBuffer> overlapping_buffer =
+ GetNextInputBuffer(0.0f, kCrossfadeSize / 3);
+
+ // The splicer should be internally queuing input since |overlapped_buffer| is
+ // part of the splice.
+ EXPECT_TRUE(AddInput(overlapped_buffer));
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // |overlapping_buffer| should not have enough data to complete the splice, so
+ // ensure output is not available.
+ EXPECT_TRUE(AddInput(overlapping_buffer));
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // Now add an EOS buffer which should complete the splice.
+ EXPECT_TRUE(AddInput(AudioBuffer::CreateEOSBuffer()));
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+
+ VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 1.0f);
+ int64 expected_crossfade_size = 0;
+ base::TimeDelta expected_crossfade_duration;
+ VerifyCrossfadeOutput(overlapped_buffer,
+ overlapping_buffer,
+ 1.0f,
+ 0.0f,
+ &expected_crossfade_duration,
+ &expected_crossfade_size);
+
+ // Ensure the last buffer is an EOS buffer.
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
+ EXPECT_TRUE(post_splice_output->end_of_stream());
+
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+}
+
+// Test crossfade when one buffer partially overlaps another, but the amount of
+// overlapped data is less than the crossfade duration.
+// +------------+
+// |111111111111|
+// +------------+
+// +--------------+
+// |22222222222222|
+// +--------------+
+// Results in:
+// +----------+-+------------+
+// |1111111111|x|222222222222|
+// +----------+-+------------+
+// Where "x" represents the crossfaded portion of the signal.
+TEST_F(AudioSplicerTest, PartialOverlapCrossfadeShortPreSplice) {
+ const int kCrossfadeSize =
+ input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
+
+ scoped_refptr<AudioBuffer> overlapped_buffer =
+ GetNextInputBuffer(1.0f, kCrossfadeSize / 2);
+
+ // Reset timestamp helper so that the next buffer will have a timestamp that
+ // starts in the middle of |overlapped_buffer|.
+ input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
+ input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() / 2);
+ const base::TimeDelta splice_timestamp =
+ input_timestamp_helper_.GetTimestamp();
+ splicer_.SetSpliceTimestamp(splice_timestamp);
+ scoped_refptr<AudioBuffer> overlapping_buffer =
+ GetNextInputBuffer(0.0f, kCrossfadeSize * 2);
+
+ // The splicer should be internally queuing input since |overlapped_buffer| is
+ // part of the splice.
+ EXPECT_TRUE(AddInput(overlapped_buffer));
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // |overlapping_buffer| should complete the splice, so ensure output is now
+ // available.
+ EXPECT_TRUE(AddInput(overlapping_buffer));
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+
+ VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 1.0f);
+
+ int64 expected_crossfade_size = 0;
+ base::TimeDelta expected_crossfade_duration;
+ VerifyCrossfadeOutput(overlapped_buffer,
+ overlapping_buffer,
+ 1.0f,
+ 0.0f,
+ &expected_crossfade_duration,
+ &expected_crossfade_size);
+
+ // Retrieve the remaining portion after crossfade.
+ ASSERT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
+ EXPECT_EQ(output_timestamp_helper_.GetTimestamp(),
+ post_splice_output->timestamp());
+ EXPECT_EQ(overlapping_buffer->duration() - expected_crossfade_duration,
+ post_splice_output->duration());
+ EXPECT_EQ(overlapping_buffer->frame_count() - expected_crossfade_size,
+ post_splice_output->frame_count());
+ EXPECT_TRUE(VerifyData(post_splice_output, 0.0f));
+
+ EXPECT_FALSE(splicer_.HasNextBuffer());
}
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698