Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: native_client_sdk/src/examples/api/audio/sine_synth.cc

Issue 14607005: [NaCl SDK] Cleanup examples. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: feedback Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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.
4
5 #include <cassert>
6 #include <cmath>
7 #include <limits>
8 #include <sstream>
9 #include "ppapi/cpp/audio.h"
10 #include "ppapi/cpp/instance.h"
11 #include "ppapi/cpp/module.h"
12 #include "ppapi/cpp/var.h"
13
14 namespace {
15 const char* const kPlaySoundId = "playSound";
16 const char* const kStopSoundId = "stopSound";
17 const char* const kSetFrequencyId = "setFrequency";
18 static const char kMessageArgumentSeparator = ':';
19
20 const double kDefaultFrequency = 440.0;
21 const double kPi = 3.141592653589;
22 const double kTwoPi = 2.0 * kPi;
23 // The sample count we will request.
24 const uint32_t kSampleFrameCount = 4096u;
25 // Only supporting stereo audio for now.
26 const uint32_t kChannels = 2u;
27 } // namespace
28
29 namespace sine_synth {
30 // The Instance class. One of these exists for each instance of your NaCl
31 // module on the web page. The browser will ask the Module object to create
32 // a new Instance for each occurrence of the <embed> tag that has these
33 // attributes:
34 // type="application/x-nacl"
35 // src="sine_synth.nmf"
36 class SineSynthInstance : public pp::Instance {
37 public:
38 explicit SineSynthInstance(PP_Instance instance)
39 : pp::Instance(instance),
40 frequency_(kDefaultFrequency),
41 theta_(0),
42 sample_frame_count_(kSampleFrameCount) {}
43 virtual ~SineSynthInstance() {}
44
45 // Called by the browser once the NaCl module is loaded and ready to
46 // initialize. Creates a Pepper audio context and initializes it. Returns
47 // true on success. Returning false causes the NaCl module to be deleted and
48 // no other functions to be called.
49 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
50
51 // Called by the browser to handle the postMessage() call in Javascript.
52 // |var_message| is expected to be a string that contains the name of the
53 // method to call. Note that the setFrequency method takes a single
54 // parameter, the frequency. The frequency parameter is encoded as a string
55 // and appended to the 'setFrequency' method name after a ':'. Examples
56 // of possible message strings are:
57 // playSound
58 // stopSound
59 // setFrequency:880
60 // If |var_message| is not a recognized method name, this method does nothing.
61 virtual void HandleMessage(const pp::Var& var_message);
62
63 // Set the frequency of the sine wave to |frequency|. Posts a message back
64 // to the browser with the new frequency value.
65 void SetFrequency(double frequency);
66
67 // The frequency property accessor.
68 double frequency() const { return frequency_; }
69
70 private:
71 static void SineWaveCallback(void* samples,
72 uint32_t buffer_size,
73 void* data) {
74 SineSynthInstance* sine_synth_instance =
75 reinterpret_cast<SineSynthInstance*>(data);
76 const double frequency = sine_synth_instance->frequency();
77 const double delta = kTwoPi * frequency / PP_AUDIOSAMPLERATE_44100;
78 const int16_t max_int16 = std::numeric_limits<int16_t>::max();
79
80 int16_t* buff = reinterpret_cast<int16_t*>(samples);
81
82 // Make sure we can't write outside the buffer.
83 assert(buffer_size >= (sizeof(*buff) * kChannels *
84 sine_synth_instance->sample_frame_count_));
85
86 for (size_t sample_i = 0;
87 sample_i < sine_synth_instance->sample_frame_count_;
88 ++sample_i, sine_synth_instance->theta_ += delta) {
89 // Keep theta_ from going beyond 2*Pi.
90 if (sine_synth_instance->theta_ > kTwoPi) {
91 sine_synth_instance->theta_ -= kTwoPi;
92 }
93 double sin_value(std::sin(sine_synth_instance->theta_));
94 int16_t scaled_value = static_cast<int16_t>(sin_value * max_int16);
95 for (size_t channel = 0; channel < kChannels; ++channel) {
96 *buff++ = scaled_value;
97 }
98 }
99 }
100
101 pp::Audio audio_;
102 double frequency_;
103
104 // The last parameter sent to the sin function. Used to prevent sine wave
105 // skips on buffer boundaries.
106 double theta_;
107
108 // The count of sample frames per channel in an audio buffer.
109 uint32_t sample_frame_count_;
110 };
111
112 bool SineSynthInstance::Init(uint32_t argc,
113 const char* argn[],
114 const char* argv[]) {
115 // Ask the device for an appropriate sample count size.
116 sample_frame_count_ = pp::AudioConfig::RecommendSampleFrameCount(
117 this, PP_AUDIOSAMPLERATE_44100, kSampleFrameCount);
118 audio_ = pp::Audio(
119 this,
120 pp::AudioConfig(this, PP_AUDIOSAMPLERATE_44100, sample_frame_count_),
121 SineWaveCallback,
122 this);
123 return true;
124 }
125
126 void SineSynthInstance::HandleMessage(const pp::Var& var_message) {
127 if (!var_message.is_string()) {
128 return;
129 }
130 std::string message = var_message.AsString();
131 if (message == kPlaySoundId) {
132 audio_.StartPlayback();
133 } else if (message == kStopSoundId) {
134 audio_.StopPlayback();
135 } else if (message.find(kSetFrequencyId) == 0) {
136 // The argument to setFrequency is everything after the first ':'.
137 size_t sep_pos = message.find_first_of(kMessageArgumentSeparator);
138 if (sep_pos != std::string::npos) {
139 std::string string_arg = message.substr(sep_pos + 1);
140 // Got the argument value as a string: try to convert it to a number.
141 std::istringstream stream(string_arg);
142 double double_value;
143 if (stream >> double_value) {
144 SetFrequency(double_value);
145 return;
146 }
147 }
148 }
149 }
150
151 void SineSynthInstance::SetFrequency(double frequency) {
152 frequency_ = frequency;
153 PostMessage(pp::Var(frequency_));
154 }
155
156 // The Module class. The browser calls the CreateInstance() method to create
157 // an instance of your NaCl module on the web page. The browser creates a new
158 // instance for each <embed> tag with type="application/x-nacl".
159 class SineSynthModule : public pp::Module {
160 public:
161 SineSynthModule() : pp::Module() {}
162 ~SineSynthModule() {}
163
164 // Create and return a HelloWorldInstance object.
165 virtual pp::Instance* CreateInstance(PP_Instance instance) {
166 return new SineSynthInstance(instance);
167 }
168 };
169
170 } // namespace sine_synth
171
172 // Factory function called by the browser when the module is first loaded.
173 // The browser keeps a singleton of this module. It calls the
174 // CreateInstance() method on the object you return to make instances. There
175 // is one instance per <embed> tag on the page. This is the main binding
176 // point for your NaCl module with the browser.
177 namespace pp {
178 Module* CreateModule() { return new sine_synth::SineSynthModule(); }
179 } // namespace pp
OLDNEW
« no previous file with comments | « native_client_sdk/src/examples/api/audio/example.dsc ('k') | native_client_sdk/src/examples/api/gamepad/example.dsc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698