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.
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"
16 const double Pi
= 3.14159265358979323846;
18 TestAudioBusFactory::TestAudioBusFactory(int num_channels
,
20 float sine_wave_frequency
,
22 : num_channels_(num_channels
),
23 sample_rate_(sample_rate
),
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
);
32 TestAudioBusFactory::~TestAudioBusFactory() {}
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(), 0);
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.
52 for (; i
< length
&& fabsf(last
) < kAmplitudeThreshold
; ++i
)
54 for (; i
< length
; ++i
) {
55 if (fabsf(samples
[i
]) >= kAmplitudeThreshold
&&
56 (last
< 0) != (samples
[i
] < 0)) {
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.
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.
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.
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;
96 bool EncodeTimestamp(uint16 timestamp
,
100 if (length
< kSamplesToAnalyze
) {
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));
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
] /
119 mix_of_components
/= kNumBits
+ 1;
120 DCHECK_LE(fabs(mix_of_components
), 1.0);
121 samples
[i
] = mix_of_components
;
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
133 double DecodeOneFrequency(const float* samples
,
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
);
142 return sqrt(sin_sum
* sin_sum
+ cos_sum
* cos_sum
);
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
],
157 if (sense
< kMinSense
) continue;
159 uint16 gray_coded
= 0;
160 for (size_t bit
= 0; success
&& bit
< kNumBits
; bit
++) {
161 double signal_strength
= DecodeOneFrequency(
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) {
170 gray_coded
|= 1 << bit
;
176 // Convert from gray-coded number to binary.
178 for (mask
= gray_coded
>> 1; mask
!= 0; mask
= mask
>> 1) {
179 gray_coded
= gray_coded
^ mask
;
181 *timestamp
= gray_coded
;