audio_hash_unittest.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright 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. #include <memory>
  5. #include "media/base/audio_bus.h"
  6. #include "media/base/audio_hash.h"
  7. #include "media/base/fake_audio_render_callback.h"
  8. #include "testing/gtest/include/gtest/gtest.h"
  9. namespace media {
  10. static const int kChannelCount = 2;
  11. static const int kFrameCount = 1024;
  12. static const int kSampleRate = 48000;
  13. class AudioHashTest : public testing::Test {
  14. public:
  15. AudioHashTest()
  16. : bus_one_(AudioBus::Create(kChannelCount, kFrameCount)),
  17. bus_two_(AudioBus::Create(kChannelCount, kFrameCount)),
  18. fake_callback_(0.01, kSampleRate) {
  19. // Fill each channel in each bus with unique data.
  20. GenerateUniqueChannels(bus_one_.get());
  21. GenerateUniqueChannels(bus_two_.get());
  22. }
  23. void GenerateUniqueChannels(AudioBus* audio_bus) {
  24. // Use an AudioBus wrapper to avoid an extra memcpy when filling channels.
  25. std::unique_ptr<AudioBus> wrapped_bus = AudioBus::CreateWrapper(1);
  26. wrapped_bus->set_frames(audio_bus->frames());
  27. // Since FakeAudioRenderCallback generates only a single channel of unique
  28. // audio data, we need to fill each channel manually.
  29. for (int ch = 0; ch < audio_bus->channels(); ++ch) {
  30. wrapped_bus->SetChannelData(0, audio_bus->channel(ch));
  31. fake_callback_.Render(base::TimeDelta(), base::TimeTicks::Now(), 0,
  32. wrapped_bus.get());
  33. }
  34. }
  35. AudioHashTest(const AudioHashTest&) = delete;
  36. AudioHashTest& operator=(const AudioHashTest&) = delete;
  37. ~AudioHashTest() override = default;
  38. protected:
  39. std::unique_ptr<AudioBus> bus_one_;
  40. std::unique_ptr<AudioBus> bus_two_;
  41. FakeAudioRenderCallback fake_callback_;
  42. };
  43. // Ensure the same data hashes the same.
  44. TEST_F(AudioHashTest, Equivalence) {
  45. AudioHash hash_one;
  46. hash_one.Update(bus_one_.get(), bus_one_->frames());
  47. AudioHash hash_two;
  48. hash_two.Update(bus_one_.get(), bus_one_->frames());
  49. EXPECT_EQ(hash_one.ToString(), hash_two.ToString());
  50. }
  51. // Ensure sample order matters to the hash.
  52. TEST_F(AudioHashTest, SampleOrder) {
  53. AudioHash original_hash;
  54. original_hash.Update(bus_one_.get(), bus_one_->frames());
  55. // Swap a sample in the bus.
  56. std::swap(bus_one_->channel(0)[0], bus_one_->channel(0)[1]);
  57. AudioHash swapped_hash;
  58. swapped_hash.Update(bus_one_.get(), bus_one_->frames());
  59. EXPECT_NE(original_hash.ToString(), swapped_hash.ToString());
  60. }
  61. // Ensure channel order matters to the hash.
  62. TEST_F(AudioHashTest, ChannelOrder) {
  63. AudioHash original_hash;
  64. original_hash.Update(bus_one_.get(), bus_one_->frames());
  65. // Reverse channel order for the same sample data.
  66. const int channels = bus_one_->channels();
  67. std::unique_ptr<AudioBus> swapped_ch_bus = AudioBus::CreateWrapper(channels);
  68. swapped_ch_bus->set_frames(bus_one_->frames());
  69. for (int i = channels - 1; i >= 0; --i)
  70. swapped_ch_bus->SetChannelData(channels - (i + 1), bus_one_->channel(i));
  71. AudioHash swapped_hash;
  72. swapped_hash.Update(swapped_ch_bus.get(), swapped_ch_bus->frames());
  73. EXPECT_NE(original_hash.ToString(), swapped_hash.ToString());
  74. }
  75. // Ensure bus order matters to the hash.
  76. TEST_F(AudioHashTest, BusOrder) {
  77. AudioHash original_hash;
  78. original_hash.Update(bus_one_.get(), bus_one_->frames());
  79. original_hash.Update(bus_two_.get(), bus_two_->frames());
  80. AudioHash reordered_hash;
  81. reordered_hash.Update(bus_two_.get(), bus_two_->frames());
  82. reordered_hash.Update(bus_one_.get(), bus_one_->frames());
  83. EXPECT_NE(original_hash.ToString(), reordered_hash.ToString());
  84. }
  85. // Ensure bus order matters to the hash even with empty buses.
  86. TEST_F(AudioHashTest, EmptyBusOrder) {
  87. bus_one_->Zero();
  88. bus_two_->Zero();
  89. AudioHash one_bus_hash;
  90. one_bus_hash.Update(bus_one_.get(), bus_one_->frames());
  91. AudioHash two_bus_hash;
  92. two_bus_hash.Update(bus_one_.get(), bus_one_->frames());
  93. two_bus_hash.Update(bus_two_.get(), bus_two_->frames());
  94. EXPECT_NE(one_bus_hash.ToString(), two_bus_hash.ToString());
  95. }
  96. // Where A = [0, n], ensure hash(A[0:n/2]), hash(A[n/2:n]) and hash(A) result
  97. // in the same value.
  98. TEST_F(AudioHashTest, HashIgnoresUpdateOrder) {
  99. AudioHash full_hash;
  100. full_hash.Update(bus_one_.get(), bus_one_->frames());
  101. AudioHash half_hash;
  102. half_hash.Update(bus_one_.get(), bus_one_->frames() / 2);
  103. // Create a new bus representing the second half of |bus_one_|.
  104. const int half_frames = bus_one_->frames() / 2;
  105. const int channels = bus_one_->channels();
  106. std::unique_ptr<AudioBus> half_bus = AudioBus::CreateWrapper(channels);
  107. half_bus->set_frames(half_frames);
  108. for (int i = 0; i < channels; ++i)
  109. half_bus->SetChannelData(i, bus_one_->channel(i) + half_frames);
  110. half_hash.Update(half_bus.get(), half_bus->frames());
  111. EXPECT_EQ(full_hash.ToString(), half_hash.ToString());
  112. }
  113. // Ensure approximate hashes pass verification.
  114. TEST_F(AudioHashTest, VerifySimilarHash) {
  115. AudioHash hash_one;
  116. hash_one.Update(bus_one_.get(), bus_one_->frames());
  117. // Twiddle the values inside the first bus.
  118. float* channel = bus_one_->channel(0);
  119. for (int i = 0; i < bus_one_->frames(); i += bus_one_->frames() / 64)
  120. channel[i] += 0.0001f;
  121. AudioHash hash_two;
  122. hash_two.Update(bus_one_.get(), bus_one_->frames());
  123. EXPECT_EQ(hash_one.ToString(), hash_two.ToString());
  124. // Twiddle the values too much...
  125. for (int i = 0; i < bus_one_->frames(); ++i)
  126. channel[i] += 0.0001f;
  127. AudioHash hash_three;
  128. hash_three.Update(bus_one_.get(), bus_one_->frames());
  129. EXPECT_NE(hash_one.ToString(), hash_three.ToString());
  130. }
  131. } // namespace media