~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit/chromium/src/AudioDestinationChromium.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Google Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 *
 
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.
 
16
 *
 
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.
 
27
 */
 
28
 
 
29
#include "config.h"
 
30
 
 
31
#if ENABLE(WEB_AUDIO)
 
32
#include "AudioDestinationChromium.h"
 
33
#include "AudioFIFO.h"
 
34
#include "AudioPullFIFO.h"
 
35
#include <public/Platform.h>
 
36
 
 
37
using namespace WebKit;
 
38
 
 
39
namespace WebCore {
 
40
 
 
41
// Buffer size at which the web audio engine will render.
 
42
const unsigned renderBufferSize = 128;
 
43
 
 
44
// Size of the FIFO
 
45
const size_t fifoSize = 8192;
 
46
 
 
47
// FIXME: add support for multi-channel.
 
48
const unsigned numberOfChannels = 2;
 
49
 
 
50
// Factory method: Chromium-implementation
 
51
PassOwnPtr<AudioDestination> AudioDestination::create(AudioIOCallback& callback, float sampleRate)
 
52
{
 
53
    return adoptPtr(new AudioDestinationChromium(callback, sampleRate));
 
54
}
 
55
 
 
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)
 
61
    , m_isPlaying(false)
 
62
{
 
63
    // Use the optimal buffer size recommended by the audio backend.
 
64
    m_callbackBufferSize = WebKit::Platform::current()->audioHardwareBufferSize();
 
65
 
 
66
    // Quick exit if the requested size is too large.
 
67
    ASSERT(m_callbackBufferSize + renderBufferSize <= fifoSize);
 
68
    if (m_callbackBufferSize + renderBufferSize > fifoSize)
 
69
        return;
 
70
 
 
71
    m_audioDevice = adoptPtr(WebKit::Platform::current()->createAudioDevice(m_callbackBufferSize, numberOfChannels, sampleRate, this));
 
72
    ASSERT(m_audioDevice);
 
73
 
 
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));
 
80
 
 
81
    // Input buffering.
 
82
    m_inputFifo = adoptPtr(new AudioFIFO(numberOfChannels, fifoSize));
 
83
 
 
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);
 
90
    }
 
91
}
 
92
 
 
93
AudioDestinationChromium::~AudioDestinationChromium()
 
94
{
 
95
    stop();
 
96
}
 
97
 
 
98
void AudioDestinationChromium::start()
 
99
{
 
100
    if (!m_isPlaying && m_audioDevice) {
 
101
        m_audioDevice->start();
 
102
        m_isPlaying = true;
 
103
    }
 
104
}
 
105
 
 
106
void AudioDestinationChromium::stop()
 
107
{
 
108
    if (m_isPlaying && m_audioDevice) {
 
109
        m_audioDevice->stop();
 
110
        m_isPlaying = false;
 
111
    }
 
112
}
 
113
 
 
114
float AudioDestination::hardwareSampleRate()
 
115
{
 
116
    return static_cast<float>(WebKit::Platform::current()->audioHardwareSampleRate());
 
117
}
 
118
 
 
119
void AudioDestinationChromium::render(const WebVector<float*>& sourceData, const WebVector<float*>& audioData, size_t numberOfFrames)
 
120
{
 
121
    bool isNumberOfChannelsGood = audioData.size() == numberOfChannels;
 
122
    if (!isNumberOfChannelsGood) {
 
123
        ASSERT_NOT_REACHED();
 
124
        return;
 
125
    }
 
126
 
 
127
    bool isBufferSizeGood = numberOfFrames == m_callbackBufferSize;
 
128
    if (!isBufferSizeGood) {
 
129
        ASSERT_NOT_REACHED();
 
130
        return;
 
131
    }
 
132
 
 
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);
 
140
    }
 
141
 
 
142
    m_renderBus.setChannelMemory(0, audioData[0], numberOfFrames);
 
143
    m_renderBus.setChannelMemory(1, audioData[1], numberOfFrames);
 
144
 
 
145
    m_fifo->consume(&m_renderBus, numberOfFrames);
 
146
}
 
147
 
 
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)
 
151
{
 
152
    bool isNumberOfChannelsGood = audioData.size() == numberOfChannels;
 
153
    if (!isNumberOfChannelsGood) {
 
154
        ASSERT_NOT_REACHED();
 
155
        return;
 
156
    }
 
157
 
 
158
    bool isBufferSizeGood = numberOfFrames == m_callbackBufferSize;
 
159
    if (!isBufferSizeGood) {
 
160
        ASSERT_NOT_REACHED();
 
161
        return;
 
162
    }
 
163
 
 
164
    m_renderBus.setChannelMemory(0, audioData[0], numberOfFrames);
 
165
    m_renderBus.setChannelMemory(1, audioData[1], numberOfFrames);
 
166
    m_fifo->consume(&m_renderBus, numberOfFrames);
 
167
}
 
168
 
 
169
void AudioDestinationChromium::provideInput(AudioBus* bus, size_t framesToProcess)
 
170
{
 
171
    AudioBus* sourceBus = 0;
 
172
    if (m_inputFifo->framesInFifo() >= framesToProcess) {
 
173
        m_inputFifo->consume(&m_inputBus, framesToProcess);
 
174
        sourceBus = &m_inputBus;
 
175
    }
 
176
 
 
177
    m_callback.render(sourceBus, bus, framesToProcess);
 
178
}
 
179
 
 
180
} // namespace WebCore
 
181
 
 
182
#endif // ENABLE(WEB_AUDIO)