2
* Copyright (C) 2010 Google Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14
* its contributors may be used to endorse or promote products derived
15
* from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
#include "AudioDestinationChromium.h"
33
#include "AudioFIFO.h"
34
#include "AudioPullFIFO.h"
35
#include <public/Platform.h>
37
using namespace WebKit;
41
// Buffer size at which the web audio engine will render.
42
const unsigned renderBufferSize = 128;
45
const size_t fifoSize = 8192;
47
// FIXME: add support for multi-channel.
48
const unsigned numberOfChannels = 2;
50
// Factory method: Chromium-implementation
51
PassOwnPtr<AudioDestination> AudioDestination::create(AudioIOCallback& callback, float sampleRate)
53
return adoptPtr(new AudioDestinationChromium(callback, sampleRate));
56
AudioDestinationChromium::AudioDestinationChromium(AudioIOCallback& callback, float sampleRate)
57
: m_callback(callback)
58
, m_inputBus(numberOfChannels, renderBufferSize)
59
, m_renderBus(numberOfChannels, renderBufferSize, false)
60
, m_sampleRate(sampleRate)
63
// Use the optimal buffer size recommended by the audio backend.
64
m_callbackBufferSize = WebKit::Platform::current()->audioHardwareBufferSize();
66
// Quick exit if the requested size is too large.
67
ASSERT(m_callbackBufferSize + renderBufferSize <= fifoSize);
68
if (m_callbackBufferSize + renderBufferSize > fifoSize)
71
m_audioDevice = adoptPtr(WebKit::Platform::current()->createAudioDevice(m_callbackBufferSize, numberOfChannels, sampleRate, this));
72
ASSERT(m_audioDevice);
74
// Create a FIFO to handle the possibility of the callback size
75
// not being a multiple of the render size. If the FIFO already
76
// contains enough data, the data will be provided directly.
77
// Otherwise, the FIFO will call the provider enough times to
78
// satisfy the request for data.
79
m_fifo = adoptPtr(new AudioPullFIFO(*this, numberOfChannels, fifoSize, renderBufferSize));
82
m_inputFifo = adoptPtr(new AudioFIFO(numberOfChannels, fifoSize));
84
// If the callback size does not match the render size, then we need to buffer some
85
// extra silence for the input. Otherwise, we can over-consume the input FIFO.
86
if (m_callbackBufferSize != renderBufferSize) {
87
// FIXME: handle multi-channel input and don't hard-code to stereo.
88
AudioBus silence(2, renderBufferSize);
89
m_inputFifo->push(&silence);
93
AudioDestinationChromium::~AudioDestinationChromium()
98
void AudioDestinationChromium::start()
100
if (!m_isPlaying && m_audioDevice) {
101
m_audioDevice->start();
106
void AudioDestinationChromium::stop()
108
if (m_isPlaying && m_audioDevice) {
109
m_audioDevice->stop();
114
float AudioDestination::hardwareSampleRate()
116
return static_cast<float>(WebKit::Platform::current()->audioHardwareSampleRate());
119
void AudioDestinationChromium::render(const WebVector<float*>& sourceData, const WebVector<float*>& audioData, size_t numberOfFrames)
121
bool isNumberOfChannelsGood = audioData.size() == numberOfChannels;
122
if (!isNumberOfChannelsGood) {
123
ASSERT_NOT_REACHED();
127
bool isBufferSizeGood = numberOfFrames == m_callbackBufferSize;
128
if (!isBufferSizeGood) {
129
ASSERT_NOT_REACHED();
133
// Buffer optional live input.
134
if (sourceData.size() >= 2) {
135
// FIXME: handle multi-channel input and don't hard-code to stereo.
136
AudioBus wrapperBus(2, numberOfFrames, false);
137
wrapperBus.setChannelMemory(0, sourceData[0], numberOfFrames);
138
wrapperBus.setChannelMemory(1, sourceData[1], numberOfFrames);
139
m_inputFifo->push(&wrapperBus);
142
m_renderBus.setChannelMemory(0, audioData[0], numberOfFrames);
143
m_renderBus.setChannelMemory(1, audioData[1], numberOfFrames);
145
m_fifo->consume(&m_renderBus, numberOfFrames);
148
// Pulls on our provider to get the rendered audio stream.
149
// FIXME: remove this method when the chromium-side switches over to the synchronized I/O render() method (above).
150
void AudioDestinationChromium::render(const WebVector<float*>& audioData, size_t numberOfFrames)
152
bool isNumberOfChannelsGood = audioData.size() == numberOfChannels;
153
if (!isNumberOfChannelsGood) {
154
ASSERT_NOT_REACHED();
158
bool isBufferSizeGood = numberOfFrames == m_callbackBufferSize;
159
if (!isBufferSizeGood) {
160
ASSERT_NOT_REACHED();
164
m_renderBus.setChannelMemory(0, audioData[0], numberOfFrames);
165
m_renderBus.setChannelMemory(1, audioData[1], numberOfFrames);
166
m_fifo->consume(&m_renderBus, numberOfFrames);
169
void AudioDestinationChromium::provideInput(AudioBus* bus, size_t framesToProcess)
171
AudioBus* sourceBus = 0;
172
if (m_inputFifo->framesInFifo() >= framesToProcess) {
173
m_inputFifo->consume(&m_inputBus, framesToProcess);
174
sourceBus = &m_inputBus;
177
m_callback.render(sourceBus, bus, framesToProcess);
180
} // namespace WebCore
182
#endif // ENABLE(WEB_AUDIO)