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

Side by Side Diff: third_party/WebKit/Source/platform/audio/AudioDestination.cpp

Issue 2501863003: Support for AudioContextOptions latencyHint. (Closed)
Patch Set: Fixes to WebAudioDeviceImpl unit test. Created 3 years, 10 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 16 matching lines...) Expand all
27 */ 27 */
28 28
29 #include "platform/audio/AudioDestination.h" 29 #include "platform/audio/AudioDestination.h"
30 30
31 #include <memory> 31 #include <memory>
32 #include "platform/Histogram.h" 32 #include "platform/Histogram.h"
33 #include "platform/audio/AudioUtilities.h" 33 #include "platform/audio/AudioUtilities.h"
34 #include "platform/audio/PushPullFIFO.h" 34 #include "platform/audio/PushPullFIFO.h"
35 #include "platform/weborigin/SecurityOrigin.h" 35 #include "platform/weborigin/SecurityOrigin.h"
36 #include "public/platform/Platform.h" 36 #include "public/platform/Platform.h"
37 #include "public/platform/WebAudioLatencyHint.h"
37 #include "public/platform/WebSecurityOrigin.h" 38 #include "public/platform/WebSecurityOrigin.h"
38 #include "wtf/PtrUtil.h" 39 #include "wtf/PtrUtil.h"
39 40
40 namespace blink { 41 namespace blink {
41 42
42 // FIFO Size. 43 // FIFO Size.
43 // 44 //
44 // TODO(hongchan): This was estimated based on the largest callback buffer size 45 // TODO(hongchan): This was estimated based on the largest callback buffer size
45 // that we would ever need. The current UMA stats indicates that this is, in 46 // that we would ever need. The current UMA stats indicates that this is, in
46 // fact, probably too small. There are Android devices out there with a size of 47 // fact, probably too small. There are Android devices out there with a size of
47 // 8000 or so. We might need to make this larger. See: crbug.com/670747 48 // 8000 or so. We might need to make this larger. See: crbug.com/670747
48 const size_t kFIFOSize = 8192; 49 const size_t kFIFOSize = 8192;
49 50
50 std::unique_ptr<AudioDestination> AudioDestination::create( 51 std::unique_ptr<AudioDestination> AudioDestination::create(
51 AudioIOCallback& callback, 52 AudioIOCallback& callback,
52 unsigned numberOfOutputChannels, 53 unsigned numberOfOutputChannels,
53 float sampleRate, 54 const WebAudioLatencyHint& latencyHint,
54 PassRefPtr<SecurityOrigin> securityOrigin) { 55 PassRefPtr<SecurityOrigin> securityOrigin) {
55 return WTF::wrapUnique(new AudioDestination( 56 return WTF::wrapUnique(new AudioDestination(callback, numberOfOutputChannels,
56 callback, numberOfOutputChannels, sampleRate, std::move(securityOrigin))); 57 latencyHint,
58 std::move(securityOrigin)));
57 } 59 }
58 60
59 AudioDestination::AudioDestination(AudioIOCallback& callback, 61 AudioDestination::AudioDestination(AudioIOCallback& callback,
60 unsigned numberOfOutputChannels, 62 unsigned numberOfOutputChannels,
61 float sampleRate, 63 const WebAudioLatencyHint& latencyHint,
62 PassRefPtr<SecurityOrigin> securityOrigin) 64 PassRefPtr<SecurityOrigin> securityOrigin)
63 : m_numberOfOutputChannels(numberOfOutputChannels), 65 : m_numberOfOutputChannels(numberOfOutputChannels),
64 m_sampleRate(sampleRate),
65 m_isPlaying(false), 66 m_isPlaying(false),
66 m_callback(callback), 67 m_callback(callback),
67 m_outputBus(AudioBus::create(numberOfOutputChannels, 68 m_outputBus(AudioBus::create(numberOfOutputChannels,
68 AudioUtilities::kRenderQuantumFrames, 69 AudioUtilities::kRenderQuantumFrames,
69 false)), 70 false)),
70 m_renderBus(AudioBus::create(numberOfOutputChannels, 71 m_renderBus(AudioBus::create(numberOfOutputChannels,
71 AudioUtilities::kRenderQuantumFrames)), 72 AudioUtilities::kRenderQuantumFrames)),
72 m_framesElapsed(0) { 73 m_framesElapsed(0) {
73 // Calculate the optimum buffer size first. 74 // Create WebAudioDevice. blink::WebAudioDevice is designed to support the
74 if (calculateBufferSize()) { 75 // local input (e.g. loopback from OS audio system), but Chromium's media
75 // Create WebAudioDevice. blink::WebAudioDevice is designed to support the 76 // renderer does not support it currently. Thus, we use zero for the number
76 // local input (e.g. loopback from OS audio system), but Chromium's media 77 // of input channels.
77 // renderer does not support it currently. Thus, we use zero for the number 78 m_webAudioDevice = WTF::wrapUnique(Platform::current()->createAudioDevice(
78 // of input channels. 79 0, numberOfOutputChannels, latencyHint, this, String(),
79 m_webAudioDevice = WTF::wrapUnique(Platform::current()->createAudioDevice( 80 std::move(securityOrigin)));
80 m_callbackBufferSize, 0, numberOfOutputChannels, sampleRate, this, 81 DCHECK(m_webAudioDevice);
81 String(), std::move(securityOrigin)));
82 DCHECK(m_webAudioDevice);
83 82
84 // Create a FIFO. 83 m_callbackBufferSize = m_webAudioDevice->framesPerBuffer();
85 m_fifo = 84
86 WTF::wrapUnique(new PushPullFIFO(numberOfOutputChannels, kFIFOSize)); 85 if (!checkBufferSize()) {
87 } else {
88 NOTREACHED(); 86 NOTREACHED();
89 } 87 }
88
89 // Create a FIFO.
90 m_fifo = WTF::wrapUnique(new PushPullFIFO(numberOfOutputChannels, kFIFOSize));
90 } 91 }
91 92
92 AudioDestination::~AudioDestination() { 93 AudioDestination::~AudioDestination() {
93 stop(); 94 stop();
94 } 95 }
95 96
96 void AudioDestination::render(const WebVector<float*>& destinationData, 97 void AudioDestination::render(const WebVector<float*>& destinationData,
97 size_t numberOfFrames, 98 size_t numberOfFrames,
98 double delay, 99 double delay,
99 double delayTimestamp, 100 double delayTimestamp,
100 size_t priorFramesSkipped) { 101 size_t priorFramesSkipped) {
101 CHECK_EQ(destinationData.size(), m_numberOfOutputChannels); 102 CHECK_EQ(destinationData.size(), m_numberOfOutputChannels);
102 CHECK_EQ(numberOfFrames, m_callbackBufferSize); 103 CHECK_EQ(numberOfFrames, m_callbackBufferSize);
103 104
104 m_framesElapsed -= std::min(m_framesElapsed, priorFramesSkipped); 105 m_framesElapsed -= std::min(m_framesElapsed, priorFramesSkipped);
105 double outputPosition = 106 double outputPosition =
106 m_framesElapsed / static_cast<double>(m_sampleRate) - delay; 107 m_framesElapsed / static_cast<double>(m_webAudioDevice->sampleRate()) -
108 delay;
107 m_outputPosition.position = outputPosition; 109 m_outputPosition.position = outputPosition;
108 m_outputPosition.timestamp = delayTimestamp; 110 m_outputPosition.timestamp = delayTimestamp;
109 m_outputPositionReceivedTimestamp = base::TimeTicks::Now(); 111 m_outputPositionReceivedTimestamp = base::TimeTicks::Now();
110 112
111 // Associate the destination data array with the output bus then fill the 113 // Associate the destination data array with the output bus then fill the
112 // FIFO. 114 // FIFO.
113 for (unsigned i = 0; i < m_numberOfOutputChannels; ++i) 115 for (unsigned i = 0; i < m_numberOfOutputChannels; ++i)
114 m_outputBus->setChannelMemory(i, destinationData[i], numberOfFrames); 116 m_outputBus->setChannelMemory(i, destinationData[i], numberOfFrames);
115 117
116 // Number of frames to render via WebAudio graph. |framesToRender > 0| means 118 // Number of frames to render via WebAudio graph. |framesToRender > 0| means
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 171
170 float AudioDestination::hardwareSampleRate() { 172 float AudioDestination::hardwareSampleRate() {
171 return static_cast<float>(Platform::current()->audioHardwareSampleRate()); 173 return static_cast<float>(Platform::current()->audioHardwareSampleRate());
172 } 174 }
173 175
174 unsigned long AudioDestination::maxChannelCount() { 176 unsigned long AudioDestination::maxChannelCount() {
175 return static_cast<unsigned long>( 177 return static_cast<unsigned long>(
176 Platform::current()->audioHardwareOutputChannels()); 178 Platform::current()->audioHardwareOutputChannels());
177 } 179 }
178 180
179 bool AudioDestination::calculateBufferSize() { 181 bool AudioDestination::checkBufferSize() {
180 // Use the optimal buffer size recommended by the audio backend.
181 size_t recommendedHardwareBufferSize = hardwareBufferSize();
182 m_callbackBufferSize = recommendedHardwareBufferSize;
183
184 #if OS(ANDROID)
185 // The optimum low-latency hardware buffer size is usually too small on
186 // Android for WebAudio to render without glitching. So, if it is small, use a
187 // larger size. If it was already large, use the requested size.
188 //
189 // Since WebAudio renders in 128-frame blocks, the small buffer sizes (144 for
190 // a Galaxy Nexus), cause significant processing jitter. Sometimes multiple
191 // blocks will processed, but other times will not be since the FIFO can
192 // satisfy the request. By using a larger callbackBufferSize, we smooth out
193 // the jitter.
194 const size_t kSmallBufferSize = 1024;
195 const size_t kDefaultCallbackBufferSize = 2048;
196
197 if (m_callbackBufferSize <= kSmallBufferSize)
198 m_callbackBufferSize = kDefaultCallbackBufferSize;
199
200 LOG(INFO) << "audioHardwareBufferSize = " << recommendedHardwareBufferSize;
201 LOG(INFO) << "callbackBufferSize = " << m_callbackBufferSize;
202 #endif
203
204 // Histogram for audioHardwareBufferSize 182 // Histogram for audioHardwareBufferSize
205 DEFINE_STATIC_LOCAL(SparseHistogram, hardwareBufferSizeHistogram, 183 DEFINE_STATIC_LOCAL(SparseHistogram, hardwareBufferSizeHistogram,
206 ("WebAudio.AudioDestination.HardwareBufferSize")); 184 ("WebAudio.AudioDestination.HardwareBufferSize"));
207 185
208 // Histogram for the actual callback size used. Typically, this is the same 186 // Histogram for the actual callback size used. Typically, this is the same
209 // as audioHardwareBufferSize, but can be adjusted depending on some 187 // as audioHardwareBufferSize, but can be adjusted depending on some
210 // heuristics below. 188 // heuristics below.
211 DEFINE_STATIC_LOCAL(SparseHistogram, callbackBufferSizeHistogram, 189 DEFINE_STATIC_LOCAL(SparseHistogram, callbackBufferSizeHistogram,
212 ("WebAudio.AudioDestination.CallbackBufferSize")); 190 ("WebAudio.AudioDestination.CallbackBufferSize"));
213 191
214 // Record the sizes if we successfully created an output device. 192 // Record the sizes if we successfully created an output device.
215 hardwareBufferSizeHistogram.sample(recommendedHardwareBufferSize); 193 hardwareBufferSizeHistogram.sample(hardwareBufferSize());
216 callbackBufferSizeHistogram.sample(m_callbackBufferSize); 194 callbackBufferSizeHistogram.sample(m_callbackBufferSize);
217 195
218 // Check if the requested buffer size is too large. 196 // Check if the requested buffer size is too large.
219 bool isBufferSizeValid = 197 bool isBufferSizeValid =
220 m_callbackBufferSize + AudioUtilities::kRenderQuantumFrames <= kFIFOSize; 198 m_callbackBufferSize + AudioUtilities::kRenderQuantumFrames <= kFIFOSize;
221 DCHECK(isBufferSizeValid); 199 DCHECK(isBufferSizeValid);
222 return isBufferSizeValid; 200 return isBufferSizeValid;
223 } 201 }
224 202
225 } // namespace blink 203 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/audio/AudioDestination.h ('k') | third_party/WebKit/public/platform/Platform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698