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.
5 // Needed on Windows to get |M_PI| from math.h.
7 #define _USE_MATH_DEFINES
16 #include "ppapi/c/pp_errors.h"
17 #include "ppapi/cpp/audio.h"
18 #include "ppapi/cpp/audio_config.h"
19 #include "ppapi/cpp/completion_callback.h"
20 #include "ppapi/cpp/instance.h"
21 #include "ppapi/cpp/module.h"
22 #include "ppapi/cpp/view.h"
24 // Separate left and right frequency to make sure we didn't swap L & R.
25 // Sounds pretty horrible, though...
26 const double kLeftFrequency
= 400;
27 const double kRightFrequency
= 1000;
29 // This sample frequency is guaranteed to work.
30 const PP_AudioSampleRate kDefaultSampleRate
= PP_AUDIOSAMPLERATE_44100
;
31 const uint32_t kDefaultSampleCount
= 4096;
33 const char kSampleRateAttributeName
[] = "samplerate";
35 class MyInstance
: public pp::Instance
{
37 explicit MyInstance(PP_Instance instance
)
38 : pp::Instance(instance
),
40 sample_rate_(kDefaultSampleRate
),
46 virtual bool Init(uint32_t argc
, const char* argn
[], const char* argv
[]) {
47 for (uint32_t i
= 0; i
< argc
; i
++) {
48 if (strcmp(kSampleRateAttributeName
, argn
[i
]) == 0) {
49 int value
= atoi(argv
[i
]);
50 if (value
> 0 && value
<= 1000000)
51 sample_rate_
= static_cast<PP_AudioSampleRate
>(value
);
57 pp::AudioConfig config
;
58 sample_count_
= pp::AudioConfig::RecommendSampleFrameCount(
59 this, sample_rate_
, kDefaultSampleCount
);
60 config
= pp::AudioConfig(this, sample_rate_
, sample_count_
);
61 audio_
= pp::Audio(this, config
, SineWaveCallbackTrampoline
, this);
62 return audio_
.StartPlayback();
65 virtual void DidChangeView(const pp::View
& view
) {
66 // The frequency will change depending on whether the page is in the
67 // foreground or background.
68 visible_
= view
.IsPageVisible();
72 static void SineWaveCallbackTrampoline(void* samples
,
75 static_cast<MyInstance
*>(thiz
)->SineWaveCallback(samples
, num_bytes
);
78 void SineWaveCallback(void* samples
, uint32_t num_bytes
) {
79 double delta_l
= 2.0 * M_PI
* kLeftFrequency
/ sample_rate_
/
81 double delta_r
= 2.0 * M_PI
* kRightFrequency
/ sample_rate_
/
84 // Use per channel audio wave value to avoid clicks on buffer boundries.
85 double wave_l
= audio_wave_l_
;
86 double wave_r
= audio_wave_r_
;
87 const int16_t max_int16
= std::numeric_limits
<int16_t>::max();
88 int16_t* buf
= reinterpret_cast<int16_t*>(samples
);
89 for (size_t sample
= 0; sample
< sample_count_
; ++sample
) {
90 *buf
++ = static_cast<int16_t>(sin(wave_l
) * max_int16
);
91 *buf
++ = static_cast<int16_t>(sin(wave_r
) * max_int16
);
92 // Add delta, keep within -2 * M_PI .. 2 * M_PI to preserve precision.
94 if (wave_l
> 2.0 * M_PI
)
97 if (wave_r
> 2.0 * M_PI
)
100 // Store current value to use as starting point for next callback.
101 audio_wave_l_
= wave_l
;
102 audio_wave_r_
= wave_r
;
107 PP_AudioSampleRate sample_rate_
;
108 uint32_t sample_count_
;
112 // Current audio wave position, used to prevent sine wave skips
113 // on buffer boundaries.
114 double audio_wave_l_
;
115 double audio_wave_r_
;
118 class MyModule
: public pp::Module
{
120 // Override CreateInstance to create your customized Instance object.
121 virtual pp::Instance
* CreateInstance(PP_Instance instance
) {
122 return new MyInstance(instance
);
128 // Factory function for your specialization of the Module object.
129 Module
* CreateModule() {
130 return new MyModule();