This source file includes following definitions.
- sample_frame_count_
- frequency
- SineWaveCallback
- Init
- HandleMessage
- SetFrequency
- CreateInstance
- CreateModule
#include <cassert>
#include <cmath>
#include <limits>
#include <sstream>
#include "ppapi/cpp/audio.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
namespace {
const char* const kPlaySoundId = "playSound";
const char* const kStopSoundId = "stopSound";
const char* const kSetFrequencyId = "setFrequency";
static const char kMessageArgumentSeparator = ':';
const double kDefaultFrequency = 440.0;
const double kPi = 3.141592653589;
const double kTwoPi = 2.0 * kPi;
const uint32_t kSampleFrameCount = 4096u;
const uint32_t kChannels = 2u;
}
class AudioInstance : public pp::Instance {
public:
explicit AudioInstance(PP_Instance instance)
: pp::Instance(instance),
frequency_(kDefaultFrequency),
theta_(0),
sample_frame_count_(kSampleFrameCount) {}
virtual ~AudioInstance() {}
virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
virtual void HandleMessage(const pp::Var& var_message);
void SetFrequency(double frequency);
double frequency() const { return frequency_; }
private:
static void SineWaveCallback(void* samples,
uint32_t buffer_size,
void* data) {
AudioInstance* instance = reinterpret_cast<AudioInstance*>(data);
const double frequency = instance->frequency();
const double delta = kTwoPi * frequency / PP_AUDIOSAMPLERATE_44100;
const int16_t max_int16 = std::numeric_limits<int16_t>::max();
int16_t* buff = reinterpret_cast<int16_t*>(samples);
assert(buffer_size >=
(sizeof(*buff) * kChannels * instance->sample_frame_count_));
for (size_t sample_i = 0; sample_i < instance->sample_frame_count_;
++sample_i, instance->theta_ += delta) {
if (instance->theta_ > kTwoPi) {
instance->theta_ -= kTwoPi;
}
double sin_value(std::sin(instance->theta_));
int16_t scaled_value = static_cast<int16_t>(sin_value * max_int16);
for (size_t channel = 0; channel < kChannels; ++channel) {
*buff++ = scaled_value;
}
}
}
pp::Audio audio_;
double frequency_;
double theta_;
uint32_t sample_frame_count_;
};
bool AudioInstance::Init(uint32_t argc,
const char* argn[],
const char* argv[]) {
sample_frame_count_ = pp::AudioConfig::RecommendSampleFrameCount(
this, PP_AUDIOSAMPLERATE_44100, kSampleFrameCount);
audio_ = pp::Audio(
this,
pp::AudioConfig(this, PP_AUDIOSAMPLERATE_44100, sample_frame_count_),
SineWaveCallback,
this);
return true;
}
void AudioInstance::HandleMessage(const pp::Var& var_message) {
if (!var_message.is_string()) {
return;
}
std::string message = var_message.AsString();
if (message == kPlaySoundId) {
audio_.StartPlayback();
} else if (message == kStopSoundId) {
audio_.StopPlayback();
} else if (message.find(kSetFrequencyId) == 0) {
size_t sep_pos = message.find_first_of(kMessageArgumentSeparator);
if (sep_pos != std::string::npos) {
std::string string_arg = message.substr(sep_pos + 1);
std::istringstream stream(string_arg);
double double_value;
if (stream >> double_value) {
SetFrequency(double_value);
return;
}
}
}
}
void AudioInstance::SetFrequency(double frequency) {
frequency_ = frequency;
PostMessage(pp::Var(frequency_));
}
class AudioModule : public pp::Module {
public:
AudioModule() : pp::Module() {}
~AudioModule() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new AudioInstance(instance);
}
};
namespace pp {
Module* CreateModule() { return new AudioModule(); }
}