This source file includes following definitions.
- source_
- NextAudioBus
- ToPcmAudioFrame
- CountZeroCrossings
- CountZeroCrossings
- EncodeTimestamp
- DecodeOneFrequency
- DecodeTimestamp
#include <math.h>
#include "media/cast/test/utility/audio_utility.h"
#include "base/time/time.h"
#include "media/base/audio_bus.h"
#include "media/cast/cast_config.h"
namespace media {
namespace cast {
const double Pi = 3.14159265358979323846;
TestAudioBusFactory::TestAudioBusFactory(int num_channels,
int sample_rate,
float sine_wave_frequency,
float volume)
: num_channels_(num_channels),
sample_rate_(sample_rate),
volume_(volume),
source_(num_channels, sine_wave_frequency, sample_rate) {
CHECK_LT(0, num_channels);
CHECK_LT(0, sample_rate);
CHECK_LE(0.0f, volume_);
CHECK_LE(volume_, 1.0f);
}
TestAudioBusFactory::~TestAudioBusFactory() {}
scoped_ptr<AudioBus> TestAudioBusFactory::NextAudioBus(
const base::TimeDelta& duration) {
const int num_samples = static_cast<int>((sample_rate_ * duration) /
base::TimeDelta::FromSeconds(1));
scoped_ptr<AudioBus> bus(AudioBus::Create(num_channels_, num_samples));
source_.OnMoreData(bus.get(), AudioBuffersState());
bus->Scale(volume_);
return bus.Pass();
}
scoped_ptr<PcmAudioFrame> ToPcmAudioFrame(const AudioBus& audio_bus,
int sample_rate) {
scoped_ptr<PcmAudioFrame> audio_frame(new PcmAudioFrame());
audio_frame->channels = audio_bus.channels();
audio_frame->frequency = sample_rate;
audio_frame->samples.resize(audio_bus.channels() * audio_bus.frames());
audio_bus.ToInterleaved(audio_bus.frames(),
sizeof(audio_frame->samples.front()),
&audio_frame->samples.front());
return audio_frame.Pass();
}
int CountZeroCrossings(const float* samples, int len) {
const float kAmplitudeThreshold = 0.03f;
int count = 0;
int i = 0;
float last = 0.0f;
for (; i < len && fabsf(last) < kAmplitudeThreshold; ++i)
last = samples[i];
for (; i < len; ++i) {
if (fabsf(samples[i]) >= kAmplitudeThreshold &&
(last < 0) != (samples[i] < 0)) {
++count;
last = samples[i];
}
}
return count;
}
int CountZeroCrossings(const std::vector<int16>& samples) {
const int kAmplitudeThreshold = 1000;
int count = 0;
std::vector<int16>::const_iterator i = samples.begin();
int16 last = 0;
for (; i != samples.end() && abs(last) < kAmplitudeThreshold; ++i)
last = *i;
for (; i != samples.end(); ++i) {
if (abs(*i) >= kAmplitudeThreshold && (last < 0) != (*i < 0)) {
++count;
last = *i;
}
}
return count;
}
const double kBaseFrequency = 200;
const int kSamplingFrequency = 48000;
const size_t kNumBits = 16;
const size_t kSamplesToAnalyze = kSamplingFrequency / kBaseFrequency;
const double kSenseFrequency = kBaseFrequency * (kNumBits + 1);
const double kMinSense = 50000.0;
bool EncodeTimestamp(uint16 timestamp,
size_t sample_offset,
std::vector<int16>* samples) {
if (samples->size() < kSamplesToAnalyze) {
return false;
}
timestamp = (timestamp >> 1) ^ timestamp;
std::vector<double> frequencies;
for (size_t i = 0; i < kNumBits; i++) {
if ((timestamp >> i) & 1) {
frequencies.push_back(kBaseFrequency * (i+1));
}
}
frequencies.push_back(kSenseFrequency);
for (size_t i = 0; i < samples->size(); i++) {
double ret = 0.0;
for (size_t f = 0; f < frequencies.size(); f++) {
ret += sin((i + sample_offset) * Pi * 2.0 * frequencies[f] /
kSamplingFrequency);
}
(*samples)[i] = ret * 32766 / (kNumBits + 1);
}
return true;
}
namespace {
double DecodeOneFrequency(const int16* samples,
size_t length,
double frequency) {
double sin_sum = 0.0;
double cos_sum = 0.0;
for (size_t i = 0; i < length; i++) {
sin_sum += samples[i] * sin(i * Pi * 2 * frequency / kSamplingFrequency);
cos_sum += samples[i] * cos(i * Pi * 2 * frequency / kSamplingFrequency);
}
return sqrt(sin_sum * sin_sum + cos_sum * cos_sum);
}
}
bool DecodeTimestamp(const std::vector<int16>& samples, uint16* timestamp) {
for (size_t start = 0;
start + kSamplesToAnalyze <= samples.size();
start += kSamplesToAnalyze / 4) {
double sense = DecodeOneFrequency(&samples[start],
kSamplesToAnalyze,
kSenseFrequency);
if (sense < kMinSense) continue;
bool success = true;
uint16 gray_coded = 0;
for (size_t bit = 0; success && bit < kNumBits; bit++) {
double signal_strength = DecodeOneFrequency(
&samples[start],
kSamplesToAnalyze,
kBaseFrequency * (bit + 1));
if (signal_strength < sense / 4) {
} else if (signal_strength > sense * 0.75 &&
signal_strength < sense * 1.25) {
gray_coded |= 1 << bit;
} else {
success = false;
}
}
if (success) {
uint16 mask;
for (mask = gray_coded >> 1; mask != 0; mask = mask >> 1) {
gray_coded = gray_coded ^ mask;
}
*timestamp = gray_coded;
return true;
}
}
return false;
}
}
}