blob: 50d418d5ba18304e3822a0fabc76b9b5ad26a921 [file] [log] [blame]
// Copyright (c) 2010 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.
// Various generator classes that generate sound samples for playback. Most
// derive off of FrameGenerator, and generate full frames (one sample for each
// channel) of sound.
//
// SineWaveGenerator -- Generates a single test tone for a given frequency.
// ASharpMinorGenerator -- Generates tones for the A# Harmonic Minor Scale.
// Why choose A# Harmonic Minor? Cause I can. (and because double-sharps
// are cool :) )
#ifndef AUTOTEST_CLIENT_SITE_TESTS_AUDIO_TONE_GENERATORS_H_
#define AUTOTEST_CLIENT_SITE_TESTS_AUDIO_TONE_GENERATORS_H_
#include <cmath>
#include <cstdlib>
#include <set>
#include <vector>
#include "common.h"
namespace autotest_client {
namespace audio {
static const double kPi = 3.14159265358979323846264338327l;
static const double kHalfPi = kPi / 2.0f;
class FrameGenerator {
public:
// Fills data with up to |buf_size| bytes with of audio frames. Only
// complete frames are written into data (ie., the number of samples written
// is a multiple of the number of channels), and |buf_size| is adjusted to
// reflect the number of bytes written into data.
//
// The |format|, and |channels|, parameters affet the size of a frame, and
// the type of sample written. The |active_channels| parameter is used to
// select which channels have samples written into them. If a channel is
// not listed in |active_channels|, then it is filled with silence. This is
// to allow generating tones on specific channels.
//
// The |active_channels| set is 0 indexed. If you have 2 channels, and you
// want to play on all of them, make sure |active_channels| contains 0, and
// 1.
virtual size_t GetFrames(SampleFormat format,
int channels,
const std::set<int>& active_channels,
void* data,
size_t buf_size) = 0;
// Returns whether or not the FrameGenerator is able to produce more frames.
// This is used to signal when one should stop calling GetFrames().
virtual bool HasMoreFrames() const = 0;
};
class SineWaveGenerator {
public:
SineWaveGenerator()
: cur_x_(0.0f) {
}
// Generates a sampled sine wave, where the sine wave period is determined
// by |frequency| and the sine wave sampling rate is determined by
// |sample_rate| (in HZ).
//
// It's probably not advisable to change |sample_rate| from call to call, but
// the API is simpler.
double Next(int sample_rate, double frequency) {
cur_x_ += (kPi * 2 * frequency) / sample_rate;
return sin(cur_x_);
}
void Reset(double cur_x = 0.0) {
cur_x_ = cur_x;
}
private:
double cur_x_;
};
class MultiToneGenerator : public FrameGenerator {
public:
MultiToneGenerator(int sample_rate, double length_sec);
virtual ~MultiToneGenerator();
void SetVolumes(double start_vol, double end_vol);
virtual void Reset(const std::vector<double> &frequencies,
bool reset_timer = false);
virtual void Reset(const double *frequencies, unsigned int ntones,
bool reset_timer = false);
virtual void Reset(double frequency, bool reset_timer = false);
virtual size_t GetFrames(SampleFormat format,
int channels,
const std::set<int>& active_channels,
void* data,
size_t buf_size);
virtual bool HasMoreFrames() const;
private:
std::vector<SineWaveGenerator> tone_wave_;
double GetFadeMagnitude() const;
int frames_generated_;
int frames_wanted_;
int fade_frames_;
std::vector<double> frequencies_;
int sample_rate_;
double cur_vol_;
double start_vol_;
double inc_vol_;
pthread_mutex_t param_mutex;
};
class ASharpMinorGenerator : public FrameGenerator {
public:
ASharpMinorGenerator(int sample_rate, double tone_length_sec);
virtual ~ASharpMinorGenerator();
void SetVolumes(double start_vol, double end_vol);
virtual void Reset();
virtual size_t GetFrames(SampleFormat format,
int channels,
const std::set<int>& active_channels,
void* data,
size_t buf_size);
virtual bool HasMoreFrames() const;
private:
static const int kNumNotes = 16;
static const double kNoteFrequencies[kNumNotes];
MultiToneGenerator tone_generator_;
int cur_note_;
};
} // namespace audio
} // namespace autotest_client
#endif // AUTOTEST_CLIENT_SITE_TESTS_AUDIO_TONE_GENERATORS_H_