1 // Copyright 2014 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 5 #include <cmath> 6 7 #include "base/basictypes.h" 8 #include "base/logging.h" 9 #include "base/time/time.h" 10 #include "media/base/audio_bus.h" 11 #include "media/cast/test/utility/audio_utility.h" 12 13 namespace media { 14 namespace cast { 15 16 const double Pi = 3.14159265358979323846; 17 18 TestAudioBusFactory::TestAudioBusFactory(int num_channels, 19 int sample_rate, 20 float sine_wave_frequency, 21 float volume) 22 : num_channels_(num_channels), 23 sample_rate_(sample_rate), 24 volume_(volume), 25 source_(num_channels, sine_wave_frequency, sample_rate) { 26 CHECK_LT(0, num_channels); 27 CHECK_LT(0, sample_rate); 28 CHECK_LE(0.0f, volume_); 29 CHECK_LE(volume_, 1.0f); 30 } 31 32 TestAudioBusFactory::~TestAudioBusFactory() {} 33 34 scoped_ptr<AudioBus> TestAudioBusFactory::NextAudioBus( 35 const base::TimeDelta& duration) { 36 const int num_samples = static_cast<int>((sample_rate_ * duration) / 37 base::TimeDelta::FromSeconds(1)); 38 scoped_ptr<AudioBus> bus(AudioBus::Create(num_channels_, num_samples)); 39 source_.OnMoreData(bus.get(), AudioBuffersState()); 40 bus->Scale(volume_); 41 return bus.Pass(); 42 } 43 44 int CountZeroCrossings(const float* samples, int length) { 45 // The sample values must pass beyond |kAmplitudeThreshold| on the opposite 46 // side of zero before a crossing will be counted. 47 const float kAmplitudeThreshold = 0.03f; // 3% of max amplitude. 48 49 int count = 0; 50 int i = 0; 51 float last = 0.0f; 52 for (; i < length && fabsf(last) < kAmplitudeThreshold; ++i) 53 last = samples[i]; 54 for (; i < length; ++i) { 55 if (fabsf(samples[i]) >= kAmplitudeThreshold && 56 (last < 0) != (samples[i] < 0)) { 57 ++count; 58 last = samples[i]; 59 } 60 } 61 return count; 62 } 63 64 // EncodeTimestamp stores a 16-bit number as frequencies in a sample. 65 // Our internal code tends to work on 10ms chunks of data, and to 66 // make sure the decoding always work, I wanted to make sure that the 67 // encoded value can be decoded from 5ms of sample data, assuming a 68 // sampling rate of 48Khz, this turns out to be 240 samples. 69 // Each bit of the timestamp is stored as a frequency, where the 70 // frequency is bit_number * 200 Hz. We also add a 'sense' tone to 71 // the output, this tone is 17 * 200 = 3400Hz, and when we decode, 72 // we can use this tone to make sure that we aren't decoding bogus data. 73 // Also, we use this tone to scale our expectations in case something 74 // changed changed the volume of the audio. 75 // 76 // Normally, we will encode 480 samples (10ms) of data, but when we 77 // read it will will scan 240 samples at a time until something that 78 // can be decoded is found. 79 // 80 // The intention is to use these routines to encode the frame number 81 // that goes with each chunk of audio, so if our frame rate is 82 // 30Hz, we would encode 48000/30 = 1600 samples of "1", then 83 // 1600 samples of "2", etc. When we decode this, it is possible 84 // that we get a chunk of data that is spanning two frame numbers, 85 // so we gray-code the numbers. Since adjacent gray-coded number 86 // will only differ in one bit, we should never get numbers out 87 // of sequence when decoding, at least not by more than one. 88 89 const double kBaseFrequency = 200; 90 const int kSamplingFrequency = 48000; 91 const size_t kNumBits = 16; 92 const size_t kSamplesToAnalyze = kSamplingFrequency / kBaseFrequency; 93 const double kSenseFrequency = kBaseFrequency * (kNumBits + 1); 94 const double kMinSense = 1.5; 95 96 bool EncodeTimestamp(uint16 timestamp, 97 size_t sample_offset, 98 size_t length, 99 float* samples) { 100 if (length < kSamplesToAnalyze) { 101 return false; 102 } 103 // gray-code the number 104 timestamp = (timestamp >> 1) ^ timestamp; 105 std::vector<double> frequencies; 106 for (size_t i = 0; i < kNumBits; i++) { 107 if ((timestamp >> i) & 1) { 108 frequencies.push_back(kBaseFrequency * (i+1)); 109 } 110 } 111 // Carrier sense frequency 112 frequencies.push_back(kSenseFrequency); 113 for (size_t i = 0; i < length; i++) { 114 double mix_of_components = 0.0; 115 for (size_t f = 0; f < frequencies.size(); f++) { 116 mix_of_components += sin((i + sample_offset) * Pi * 2.0 * frequencies[f] / 117 kSamplingFrequency); 118 } 119 mix_of_components /= kNumBits + 1; 120 DCHECK_LE(fabs(mix_of_components), 1.0); 121 samples[i] = mix_of_components; 122 } 123 return true; 124 } 125 126 namespace { 127 // We use a slow DCT here since this code is only used for testing. 128 // While an FFT would probably be faster, it wouldn't be a LOT 129 // faster since we only analyze 17 out of 120 frequencies. 130 // With an FFT we would verify that none of the higher frequencies 131 // contain a lot of energy, which would be useful in detecting 132 // bogus data. 133 double DecodeOneFrequency(const float* samples, 134 size_t length, 135 double frequency) { 136 double sin_sum = 0.0; 137 double cos_sum = 0.0; 138 for (size_t i = 0; i < length; i++) { 139 sin_sum += samples[i] * sin(i * Pi * 2 * frequency / kSamplingFrequency); 140 cos_sum += samples[i] * cos(i * Pi * 2 * frequency / kSamplingFrequency); 141 } 142 return sqrt(sin_sum * sin_sum + cos_sum * cos_sum); 143 } 144 } // namespace 145 146 // When decoding, we first check for sense frequency, then we decode 147 // each of the bits. Each frequency must have a strength that is similar to 148 // the sense frequency or to zero, or the decoding fails. If it fails, we 149 // move head by 60 samples and try again until we run out of samples. 150 bool DecodeTimestamp(const float* samples, size_t length, uint16* timestamp) { 151 for (size_t start = 0; 152 start + kSamplesToAnalyze <= length; 153 start += kSamplesToAnalyze / 4) { 154 double sense = DecodeOneFrequency(&samples[start], 155 kSamplesToAnalyze, 156 kSenseFrequency); 157 if (sense < kMinSense) continue; 158 bool success = true; 159 uint16 gray_coded = 0; 160 for (size_t bit = 0; success && bit < kNumBits; bit++) { 161 double signal_strength = DecodeOneFrequency( 162 &samples[start], 163 kSamplesToAnalyze, 164 kBaseFrequency * (bit + 1)); 165 if (signal_strength < sense / 4) { 166 // Zero bit, no action 167 } else if (signal_strength > sense * 0.75 && 168 signal_strength < sense * 1.25) { 169 // One bit 170 gray_coded |= 1 << bit; 171 } else { 172 success = false; 173 } 174 } 175 if (success) { 176 // Convert from gray-coded number to binary. 177 uint16 mask; 178 for (mask = gray_coded >> 1; mask != 0; mask = mask >> 1) { 179 gray_coded = gray_coded ^ mask; 180 } 181 *timestamp = gray_coded; 182 return true; 183 } 184 } 185 return false; 186 } 187 188 } // namespace cast 189 } // namespace media 190