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