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

Side by Side Diff: chrome/renderer/audio_device.cc

Issue 6002005: Implement renderer AudioDevice API for low-latency audio output... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "chrome/renderer/audio_device.h"
6
7 #include "base/singleton.h"
8 #include "chrome/common/render_messages_params.h"
9 #include "chrome/renderer/render_thread.h"
10 #include "media/audio/audio_util.h"
11
12 scoped_refptr<AudioMessageFilter> AudioDevice::filter_;
13
14 namespace {
15
16 // AudioMessageFilterCreator is intended to be used as a singleton so we can
17 // get access to a shared AudioMessageFilter.
18 // Example usage:
19 // AudioMessageFilter* filter = AudioMessageFilterCreator::SharedFilter();
20
21 class AudioMessageFilterCreator {
scherkus (not reviewing) 2011/01/12 21:32:10 nice!
22 public:
23 AudioMessageFilterCreator() {
24 int routing_id;
25 RenderThread::current()->Send(
26 new ViewHostMsg_GenerateRoutingID(&routing_id));
27 filter_ = new AudioMessageFilter(routing_id);
28 RenderThread::current()->AddFilter(filter_);
29 }
30
31 static AudioMessageFilter* SharedFilter() {
32 return GetInstance()->filter_.get();
33 }
34
35 static AudioMessageFilterCreator* GetInstance() {
36 return Singleton<AudioMessageFilterCreator>::get();
37 }
38
39 private:
40 scoped_refptr<AudioMessageFilter> filter_;
41 };
42
43 }
44
45 AudioDevice::AudioDevice(size_t buffer_size,
46 int channels,
47 double sample_rate,
48 RenderCallback* callback)
49 : buffer_size_(buffer_size),
50 channels_(channels),
51 sample_rate_(sample_rate),
52 callback_(callback),
53 stream_id_(0) {
54 audio_data_.reserve(channels);
55 for (int i = 0; i < channels; ++i) {
56 float* channel_data = new float[buffer_size];
57 audio_data_.push_back(channel_data);
58 }
59 }
60
61 AudioDevice::~AudioDevice() {
62 Stop();
63 for (int i = 0; i < channels_; ++i)
64 delete [] audio_data_[i];
65 }
66
67 bool AudioDevice::Start() {
68 // Make sure we don't call Start() more than once.
69 DCHECK_EQ(0, stream_id_);
70 if (stream_id_)
71 return false;
72
73 // Lazily create the message filter and share across AudioDevice instances.
74 filter_ = AudioMessageFilterCreator::SharedFilter();
75
76 stream_id_ = filter_->AddDelegate(this);
77
78 ViewHostMsg_Audio_CreateStream_Params params;
79 params.params.format = AudioParameters::AUDIO_PCM_LINEAR;
80 params.params.channels = channels_;
81 params.params.sample_rate = sample_rate_;
82 params.params.bits_per_sample = 16;
83 params.params.samples_per_packet = buffer_size_;
84
85 filter_->Send(
86 new ViewHostMsg_CreateAudioStream(0, stream_id_, params, true));
87
88 return true;
89 }
90
91 bool AudioDevice::Stop() {
92 if (stream_id_) {
93 OnDestroy();
94 return true;
95 }
96 return false;
97 }
98
99 void AudioDevice::OnDestroy() {
100 // Make sure we don't call destroy more than once.
101 DCHECK_NE(0, stream_id_);
102 if (!stream_id_)
103 return;
104
105 filter_->RemoveDelegate(stream_id_);
106 filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_));
107 stream_id_ = 0;
108 if (audio_thread_.get()) {
109 socket_->Close();
110 audio_thread_->Join();
111 }
112 }
113
114 void AudioDevice::OnRequestPacket(AudioBuffersState buffers_state) {
115 // This method does not apply to the low-latency system.
116 NOTIMPLEMENTED();
117 }
118
119 void AudioDevice::OnStateChanged(
120 const ViewMsg_AudioStreamState_Params& state) {
121 // Not needed in this simple implementation.
122 NOTIMPLEMENTED();
123 }
124
125 void AudioDevice::OnCreated(
126 base::SharedMemoryHandle handle, uint32 length) {
127 // Not needed in this simple implementation.
128 NOTIMPLEMENTED();
129 }
130
131 void AudioDevice::OnLowLatencyCreated(
132 base::SharedMemoryHandle handle,
133 base::SyncSocket::Handle socket_handle,
134 uint32 length) {
135
136 #if defined(OS_WIN)
137 DCHECK(handle);
138 DCHECK(socket_handle);
139 #else
140 DCHECK_GE(handle.fd, 0);
141 DCHECK_GE(socket_handle, 0);
142 #endif
143 DCHECK(length);
144 DCHECK(!audio_thread_.get());
145
146 // TODO(crogers) : check that length is big enough for buffer_size_
147
148 shared_memory_.reset(new base::SharedMemory(handle, false));
149 shared_memory_->Map(length);
150
151 socket_.reset(new base::SyncSocket(socket_handle));
152 // Allow the client to pre-populate the buffer.
153 FireRenderCallback();
154
155 // TODO(crogers): we could optionally set the thread to high-priority
156 audio_thread_.reset(
157 new base::DelegateSimpleThread(this, "renderer_audio_thread"));
158 audio_thread_->Start();
159
160 filter_->Send(new ViewHostMsg_PlayAudioStream(0, stream_id_));
161 }
162
163 void AudioDevice::OnVolume(double volume) {
164 // Not needed in this simple implementation.
165 NOTIMPLEMENTED();
166 }
167
168 // Our audio thread runs here.
169 void AudioDevice::Run() {
170 int pending_data;
171 while (sizeof(pending_data) == socket_->Receive(&pending_data,
172 sizeof(pending_data)) &&
173 pending_data >= 0) {
174 FireRenderCallback();
175 }
176 }
177
178 void AudioDevice::FireRenderCallback() {
179 if (callback_) {
180 // Ask client to render audio.
181 callback_->Render(audio_data_, buffer_size_);
182
183 // Interleave, scale, and clip to int16.
184 int16* output_buffer16 = static_cast<int16*>(shared_memory_data());
185 media::InterleaveFloatToInt16(audio_data_, output_buffer16, buffer_size_);
186 }
187 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698