Index: ppapi/native_client/tests/ppapi_simple_tests/audio.cc |
=================================================================== |
--- ppapi/native_client/tests/ppapi_simple_tests/audio.cc (revision 0) |
+++ ppapi/native_client/tests/ppapi_simple_tests/audio.cc (revision 0) |
@@ -0,0 +1,154 @@ |
+// Copyright (c) 2011 The Native Client Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+// |
+ |
+#include <stdint.h> |
+ |
+#include <cmath> |
+#include <limits> |
+#include <string> |
+ |
+#include <nacl/nacl_check.h> |
+#include <nacl/nacl_log.h> |
+ |
+#include "ppapi/c/pp_bool.h" |
+#include "ppapi/c/pp_errors.h" |
+#include "ppapi/c/ppb_audio.h" |
+#include "ppapi/c/ppb_audio_config.h" |
+#include "ppapi/cpp/audio.h" |
+#include "ppapi/cpp/audio_config.h" |
+#include "ppapi/cpp/completion_callback.h" |
+#include "ppapi/cpp/instance.h" |
+#include "ppapi/cpp/module.h" |
+ |
+const PP_AudioSampleRate kSampleFrequency = PP_AUDIOSAMPLERATE_44100; |
+// Buffer size in units of sample frames. |
+// 4096 is a conservative size that should avoid underruns on most systems. |
+const uint32_t kSampleFrameCount = 4096; |
+const uint32_t kDefaultFrequency = 400; |
+const uint32_t kDefaultDuration = 10000; |
+ |
+const int kNumChannelsForStereo = 2; |
+const size_t kSizeSingleSample = kNumChannelsForStereo * sizeof(int16_t); |
+ |
+const double kPi = 3.141592653589; |
+const double kTwoPi = 2.0 * kPi; |
+ |
+class MyInstance : public pp::Instance { |
+ private: |
+ pp::Audio audio_; |
+ uint32_t obtained_sample_frame_count_; |
+ double audio_wave_time_; // between -kTwoPi, +kTwoPi |
+ uint32_t duration_; // in msec |
+ uint32_t frequency_; |
+ |
+ static void SoundCallback(void* samples, uint32_t num_bytes, void* thiz) { |
+ MyInstance* instance = reinterpret_cast<MyInstance*>(thiz); |
+ // CHECK inside callback is only for testing purposes. |
+ CHECK(instance->obtained_sample_frame_count_ * kSizeSingleSample == |
+ num_bytes); |
+ const double delta = kTwoPi * instance->frequency_ / kSampleFrequency; |
+ const int16_t max_int16 = std::numeric_limits<int16_t>::max(); |
+ int16_t* buf = reinterpret_cast<int16_t*>(samples); |
+ for (size_t i = 0; i < instance->obtained_sample_frame_count_; ++i) { |
+ const double v = sin(instance->audio_wave_time_) * max_int16; |
+ *buf++ = static_cast<int16_t>(v); |
+ *buf++ = static_cast<int16_t>(v); |
+ // Add delta, keep within -kTwoPi, +TwoPi to preserve precision. |
+ instance->audio_wave_time_ += delta; |
+ if (instance->audio_wave_time_ > kTwoPi) |
+ instance->audio_wave_time_ -= kTwoPi * 2.0; |
+ } |
+ } |
+ |
+ static void StopOutput(void* thiz, int32_t err) { |
+ if (PP_OK == err) { |
+ MyInstance* instance = static_cast<MyInstance*>(thiz); |
+ instance->audio_.StopPlayback(); |
+ } |
+ } |
+ |
+ void ExtraChecks(pp::AudioConfig* config) { |
+ CHECK(obtained_sample_frame_count_ >= PP_AUDIOMINSAMPLEFRAMECOUNT); |
+ CHECK(obtained_sample_frame_count_ <= PP_AUDIOMAXSAMPLEFRAMECOUNT); |
+ |
+ PPB_GetInterface get_browser_if = |
+ pp::Module::Get()->get_browser_interface(); |
+ |
+ const struct PPB_AudioConfig* audio_config_if = |
+ static_cast<const struct PPB_AudioConfig*>( |
+ get_browser_if(PPB_AUDIO_CONFIG_INTERFACE)); |
+ |
+ const struct PPB_Audio* audio_if = |
+ static_cast<const struct PPB_Audio*>( |
+ get_browser_if(PPB_AUDIO_INTERFACE)); |
+ |
+ CHECK(NULL != audio_config_if); |
+ CHECK(NULL != audio_if); |
+ |
+ const PP_Resource audio_config_res = config->pp_resource(); |
+ const PP_Resource audio_res = audio_.pp_resource(); |
+ |
+ CHECK(PP_TRUE == audio_config_if->IsAudioConfig(audio_config_res)); |
+ CHECK(PP_TRUE == audio_if->IsAudio(audio_res)); |
+ CHECK(PP_FALSE == audio_config_if->IsAudioConfig(audio_res)); |
+ CHECK(PP_FALSE == audio_if->IsAudio(audio_config_res)); |
+ CHECK(audio_if->GetCurrentConfig(audio_res) == audio_config_res); |
+ CHECK(0 == audio_if->GetCurrentConfig(audio_config_res)); |
+ CHECK(audio_config_if->GetSampleRate(audio_config_res) == |
+ config->sample_rate()); |
+ CHECK(audio_config_if->GetSampleFrameCount(audio_config_res) == |
+ config->sample_frame_count()); |
+ CHECK(audio_.config().pp_resource() == audio_config_res); |
+ } |
+ |
+ void ParseArgs(uint32_t argc, const char* argn[], const char* argv[]) { |
+ for (uint32_t i = 0; i < argc; ++i) { |
+ const std::string tag = argn[i]; |
+ if (tag == "duration") duration_ = strtol(argv[i], 0, 0); |
+ if (tag == "frequency") frequency_ = strtol(argv[i], 0, 0); |
+ } |
+ } |
+ |
+ public: |
+ explicit MyInstance(PP_Instance instance) |
+ : pp::Instance(instance), |
+ duration_(kDefaultDuration), frequency_(kDefaultFrequency) {} |
+ |
+ virtual ~MyInstance() {} |
+ |
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { |
+ ParseArgs(argc, argn, argv); |
+ obtained_sample_frame_count_ = pp::AudioConfig::RecommendSampleFrameCount( |
+ kSampleFrequency, kSampleFrameCount); |
+ |
+ pp::AudioConfig config = |
+ pp::AudioConfig(this, kSampleFrequency, obtained_sample_frame_count_); |
+ |
+ audio_ = pp::Audio(this, config, SoundCallback, this); |
+ |
+ ExtraChecks(&config); |
+ |
+ CHECK(audio_.StartPlayback()); |
+ |
+ pp::CompletionCallback cc(StopOutput, this); |
+ pp::Module::Get()->core()->CallOnMainThread(duration_, cc, PP_OK); |
+ return true; |
+ } |
+}; |
+ |
+// standard boilerplate code below |
+class MyModule : public pp::Module { |
+ public: |
+ virtual pp::Instance* CreateInstance(PP_Instance instance) { |
+ return new MyInstance(instance); |
+ } |
+}; |
+ |
+namespace pp { |
+Module* CreateModule() { |
+ return new MyModule(); |
+} |
+ |
+} // namespace pp |