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

Side by Side Diff: ppapi/examples/audio_input/audio_input.cc

Issue 8662020: Pepper: Add an example/test plugin for audio input (a.k.a. microphone). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years 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
« no previous file with comments | « no previous file | ppapi/examples/audio_input/audio_input.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <string.h>
6
7 #include <algorithm>
8
9 #include "ppapi/cpp/audio_config.h"
10 #include "ppapi/cpp/completion_callback.h"
11 #include "ppapi/cpp/dev/audio_input_dev.h"
12 #include "ppapi/cpp/graphics_2d.h"
13 #include "ppapi/cpp/image_data.h"
14 #include "ppapi/cpp/instance.h"
15 #include "ppapi/cpp/logging.h"
16 #include "ppapi/cpp/module.h"
17 #include "ppapi/cpp/rect.h"
18 #include "ppapi/cpp/size.h"
19
20 class MyInstance : public pp::Instance {
21 public:
22 explicit MyInstance(PP_Instance instance)
23 : pp::Instance(instance),
24 callback_factory_(this),
25 sample_count_(0),
26 channel_count_(0),
27 samples_(NULL),
28 timer_interval_(0),
29 pending_paint_(false),
30 waiting_for_flush_completion_(false) {
31 }
32 virtual ~MyInstance() {
33 audio_input_.StopCapture();
34 delete[] samples_;
35 }
36
37 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
38 // This sample frequency is guaranteed to work.
39 const PP_AudioSampleRate kSampleFrequency = PP_AUDIOSAMPLERATE_44100;
40 const uint32_t kSampleCount = 1024;
41 const uint32_t kChannelCount = 1;
42
43 sample_count_ = pp::AudioConfig::RecommendSampleFrameCount(kSampleFrequency,
44 kSampleCount);
45 PP_DCHECK(sample_count_ > 0);
46 channel_count_ = kChannelCount;
47 pp::AudioConfig config = pp::AudioConfig(this,
48 kSampleFrequency,
49 sample_count_);
50 samples_ = new int16_t[sample_count_ * channel_count_];
51 memset(samples_, 0, sample_count_ * channel_count_ * sizeof(int16_t));
52 audio_input_ = pp::AudioInput_Dev(this, config, CaptureCallback, this);
53 if (!audio_input_.StartCapture())
54 return false;
55
56 // Try to ensure that we pick up a new set of samples between each
57 // timer-generated repaint.
58 timer_interval_ = 44100 / sample_count_ + 5;
dmichael (off chromium) 2011/11/23 20:15:52 This doesn't make sense to me. timer_interval_ is
viettrungluu 2011/11/23 21:06:25 Right, good catch. Fixed.
59 ScheduleNextTimer();
60
61 return true;
62 }
63
64 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
65 if (position.size() == size_)
66 return;
67
68 size_ = position.size();
69 device_context_ = pp::Graphics2D(this, size_, false);
70 if (!BindGraphics(device_context_))
71 return;
72
73 Paint();
74 }
75
76 private:
77 void ScheduleNextTimer() {
78 PP_DCHECK(timer_interval_ > 0);
79 pp::Module::Get()->core()->CallOnMainThread(
80 timer_interval_,
81 callback_factory_.NewRequiredCallback(&MyInstance::OnTimer),
82 0);
83 }
84
85 void OnTimer(int32_t) {
86 ScheduleNextTimer();
87 Paint();
88 }
89
90 void DidFlush(int32_t result) {
91 waiting_for_flush_completion_ = false;
92 if (pending_paint_) {
93 pending_paint_ = false;
94 Paint();
95 }
96 }
97
98 void Paint() {
99 if (size_.IsEmpty()) {
100 pending_paint_ = false;
101 return;
102 }
103
104 if (waiting_for_flush_completion_) {
105 pending_paint_ = true;
106 return;
107 }
108
109 pp::ImageData image = PaintImage(size_,
110 samples_,
111 sample_count_,
112 channel_count_);
113 if (!image.is_null()) {
114 device_context_.ReplaceContents(&image);
115 waiting_for_flush_completion_ = true;
116 device_context_.Flush(
117 callback_factory_.NewRequiredCallback(&MyInstance::DidFlush));
118 }
119 }
120
121 pp::ImageData PaintImage(const pp::Size& size,
122 const int16_t* samples,
123 uint32_t sample_count,
124 uint32_t channel_count) {
dmichael (off chromium) 2011/11/23 20:15:52 nit: Is there a reason to use parameters for these
viettrungluu 2011/11/23 21:06:25 No good reason; I got rid of the last three parame
125 pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
126 if (image.is_null())
127 return image;
128
129 // Clear to dark grey.
130 for (int y = 0; y < size.height(); y++) {
131 for (int x = 0; x < size.width(); x++)
132 *image.GetAddr32(pp::Point(x, y)) = 0xff202020;
133 }
134
135 int mid_height = size.height() / 2;
136 int max_amplitude = size.height() * 4 / 10;
137
138 // Draw some lines.
139 for (int x = 0; x < size.width(); x++) {
140 *image.GetAddr32(pp::Point(x, mid_height)) = 0xff606060;
141 *image.GetAddr32(pp::Point(x, mid_height + max_amplitude)) = 0xff404040;
142 *image.GetAddr32(pp::Point(x, mid_height - max_amplitude)) = 0xff404040;
143 }
144
145 // Draw our samples.
146 for (int x = 0, i = 0;
147 x < std::min(size.width(), static_cast<int>(sample_count));
148 x++, i += channel_count) {
149 int y = samples[i] * max_amplitude / 32768 + mid_height;
dmichael (off chromium) 2011/11/23 20:15:52 nit: std::numeric_limits<int16_t>::max()+1 might l
viettrungluu 2011/11/23 21:06:25 Done.
150 *image.GetAddr32(pp::Point(x, y)) = 0xffffffff;
151 }
152
153 return image;
154 }
155
156 // TODO(viettrungluu): Danger! We really should lock, but which thread
dmichael (off chromium) 2011/11/23 20:15:52 I have some threading primitive wrappers sitting s
157 // primitives to use? In any case, the |StopCapture()| in the destructor
158 // shouldn't return until this callback is done, so at least we should be
159 // writing to a valid region of memory.
dmichael (off chromium) 2011/11/23 20:15:52 But I agree... in this case, the worst that will h
viettrungluu 2011/11/23 21:06:25 Yeah, we should fix it, but let's hold off on it f
160 static void CaptureCallback(const void* samples,
161 uint32_t num_bytes,
162 void* ctx) {
163 MyInstance* thiz = reinterpret_cast<MyInstance*>(ctx);
dmichael (off chromium) 2011/11/23 20:15:52 static_cast
viettrungluu 2011/11/23 21:06:25 Done.
164 PP_DCHECK(num_bytes ==
165 thiz->sample_count_ * channel_count_ * sizeof(int16_t));
166 memcpy(thiz->samples_, samples, num_bytes);
167 }
168
169 pp::CompletionCallbackFactory<MyInstance> callback_factory_;
170
171 uint32_t sample_count_;
172 uint32_t channel_count_;
173 int16_t* samples_;
174
175 int32_t timer_interval_;
176
177 // Painting stuff.
178 pp::Size size_;
179 pp::Graphics2D device_context_;
180 bool pending_paint_;
181 bool waiting_for_flush_completion_;
182
183
yzshen1 2011/11/23 21:21:17 One redundant empty line could be removed.
viettrungluu 2011/11/23 21:31:30 Done.
184 // Allocated in |Init()|, freed on destruction.
185 pp::AudioInput_Dev audio_input_;
yzshen1 2011/11/23 21:21:17 nit: Allocated / freed may not be accurate. It sou
viettrungluu 2011/11/23 21:31:30 I removed this misleading comment (which I forgot
186 };
187
188 class MyModule : public pp::Module {
189 public:
190 virtual pp::Instance* CreateInstance(PP_Instance instance) {
191 return new MyInstance(instance);
192 }
193 };
194
195 namespace pp {
196
197 // Factory function for your specialization of the Module object.
198 Module* CreateModule() {
199 return new MyModule();
200 }
201
202 } // namespace pp
OLDNEW
« no previous file with comments | « no previous file | ppapi/examples/audio_input/audio_input.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698