blob: bb46a3dc1cd463c4d74c388ffb14f622feb65af4 [file] [log] [blame]
// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef AUDIOTEST_FRAME_GENERATOR_H_
#define AUDIOTEST_FRAME_GENERATOR_H_
#include <atomic>
#include <cmath>
#include <condition_variable>
#include <mutex>
#include <set>
#include <thread>
#include <vector>
#include "connector.h"
#include "param_config.h"
using std::vector;
using std::set;
namespace autotest_client {
namespace audio {
// Sine wave is a object recording
// the current amplitude of the specific frequency
// with respect to sample rate.
class SineWave {
public:
explicit SineWave(int sample_rate, double freq = 0.0)
: frequency_(freq),
x_(0.0),
sample_rate_(sample_rate) {}
// Resets the frequency of wave.
void Reset(double freq) {
frequency_ = freq;
x_ = 0.0;
}
// Get next sample.
double GetNext() {
x_ += (2 * M_PI * frequency_) / static_cast<double>(sample_rate_);
return sin(x_);
}
private:
double frequency_;
double x_;
int sample_rate_;
};
// Control the generating thread
// which generates frames with respect to specified frequency
// and write to player process.
class FrameGenerator {
public:
explicit FrameGenerator(const ParamConfig& config);
// Start generating thread and play.
inline void PlayTo(PlayClient *player) {
generating_thread_ = std::thread(&FrameGenerator::Run, this, player);
}
// Reset the frequencies to be generated.
void SetFrequency(double freq);
// Tell player thread to stop playing current frequency.
inline void SetStopPlayTone() {
stop_play_tone_ = true;
}
void Stop();
private:
// The function of generating thread.
// Keep direct frames to player whenever frequency is available.
void Run(PlayClient *player);
// Generates frames and put into the buffer.
// Returns number of frames generated.
unsigned GetFrames(double *buf, unsigned num_frames);
// Returns true if there is more frames to be generated.
bool HasMoreFrames() const;
// Get magnitude for single frame by frequency, fading, etc.
double GetSample();
// Calculate the fading-in proportion
// so it won't hurt the speaker by directly play with huge volume.
double FadingMagnitude() const;
std::thread generating_thread_;
// Two states when playing
// use change_state_mutex & change_state_cond to update.
bool terminate_test_;
bool new_freq_;
// Use this to avoid additional tones played.
std::atomic<bool> stop_play_tone_;
std::mutex change_state_mutex_;
std::condition_variable change_state_cond_;
// Frame records.
int frames_needed_;
int frames_generated_;
// Static data for tone generator.
int fft_size_;
int sample_rate_;
double tone_length_;
double cur_volume_, volume_gap_;
int num_channels_;
set<int> active_channels_;
SampleFormat format_;
SineWave wave_;
int num_fade_frames_;
bool is_debug_;
};
} // namespace audio
} // namespace autotest_client
#endif // AUDIOTEST_FRAME_GENERATOR_H_