15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef MEDIA_CAST_TEST_UTILITY_AUDIO_UTILITY_H_
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define MEDIA_CAST_TEST_UTILITY_AUDIO_UTILITY_H_
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/audio/simple_sources.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace base {
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class TimeDelta;
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace media {
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class AudioBus;
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace media {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace cast {
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Produces AudioBuses of varying duration where each successive output contains
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// the continuation of a single sine wave.
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class TestAudioBusFactory {
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestAudioBusFactory(int num_channels,
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      int sample_rate,
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      float sine_wave_frequency,
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      float volume);
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ~TestAudioBusFactory();
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Creates a new AudioBus of the given |duration|, filled with the next batch
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // of sine wave samples.
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<AudioBus> NextAudioBus(const base::TimeDelta& duration);
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // A reasonable test tone.
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static const int kMiddleANoteFreq = 440;
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int num_channels_;
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int sample_rate_;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const float volume_;
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SineWaveAudioSource source_;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestAudioBusFactory);
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Assuming |samples| contains a single-frequency sine wave (and maybe some
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// low-amplitude noise), count the number of times the sine wave crosses
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// zero.
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch//
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Example use case: When expecting a 440 Hz tone, this can be checked using the
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// following expression:
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch//
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch//   abs((CountZeroCrossings(...) / seconds_per_frame / 2) - 440) <= 1
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch//
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// ...where seconds_per_frame is the number of samples divided by the sampling
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// rate.  The divide by two accounts for the fact that a sine wave crosses zero
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// twice per cycle (first downwards, then upwards).  The absolute maximum
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// difference of 1 accounts for the sine wave being out of perfect phase.
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint CountZeroCrossings(const float* samples, int length);
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Encode |timestamp| into the samples pointed to by 'samples' in a way
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// that should be decodable even after compressing/decompressing the audio.
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Assumes 48Khz sampling rate and needs at least 240 samples. Returns
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// false if |length| of |samples| is too small. If more than 240 samples are
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// available, then the timestamp will be repeated. |sample_offset| should
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// contain how many samples has been encoded so far, so that we can make smooth
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// transitions between encoded chunks.
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// See audio_utility.cc for details on how the encoding is done.
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool EncodeTimestamp(uint16 timestamp,
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     size_t sample_offset,
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     size_t length,
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     float* samples);
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Decode a timestamp encoded with EncodeTimestamp. Returns true if a
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// timestamp was found in |samples|.
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DecodeTimestamp(const float* samples, size_t length, uint16* timestamp);
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace cast
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace media
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // MEDIA_CAST_TEST_UTILITY_AUDIO_UTILITY_H_
83