Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / audio / AudioFIFO.cpp
1 /*
2  * Copyright (C) 2012 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
33 #include "platform/audio/AudioFIFO.h"
34
35 namespace blink {
36
37 AudioFIFO::AudioFIFO(unsigned numberOfChannels, size_t fifoLength)
38     : m_fifoAudioBus(AudioBus::create(numberOfChannels, fifoLength))
39     , m_fifoLength(fifoLength)
40     , m_framesInFifo(0)
41     , m_readIndex(0)
42     , m_writeIndex(0)
43 {
44 }
45
46 void AudioFIFO::consume(AudioBus* destination, size_t framesToConsume)
47 {
48     bool isGood = destination && (framesToConsume <= m_fifoLength) && (framesToConsume <= m_framesInFifo) && (destination->length() >= framesToConsume);
49     ASSERT(isGood);
50     if (!isGood)
51         return;
52
53     // Copy the requested number of samples to the destination.
54
55     size_t part1Length;
56     size_t part2Length;
57     findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length);
58
59     size_t numberOfChannels = m_fifoAudioBus->numberOfChannels();
60
61     for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
62         float* destinationData = destination->channel(channelIndex)->mutableData();
63         const float* sourceData = m_fifoAudioBus->channel(channelIndex)->data();
64
65         bool isCopyGood = ((m_readIndex < m_fifoLength)
66                            && (m_readIndex + part1Length) <= m_fifoLength
67                            && (part1Length <= destination->length())
68                            && (part1Length + part2Length) <= destination->length());
69         ASSERT(isCopyGood);
70         if (!isCopyGood)
71             return;
72
73         memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData));
74         // Handle wrap around of the FIFO, if needed.
75         if (part2Length)
76             memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData));
77     }
78     m_readIndex = updateIndex(m_readIndex, framesToConsume);
79     ASSERT(m_framesInFifo >= framesToConsume);
80     m_framesInFifo -= framesToConsume;
81 }
82
83 void AudioFIFO::push(const AudioBus* sourceBus)
84 {
85     // Copy the sourceBus into the FIFO buffer.
86
87     bool isGood = sourceBus && (m_framesInFifo + sourceBus->length() <= m_fifoLength);
88     if (!isGood)
89         return;
90
91     size_t sourceLength = sourceBus->length();
92     size_t part1Length;
93     size_t part2Length;
94     findWrapLengths(m_writeIndex, sourceLength, part1Length, part2Length);
95
96     size_t numberOfChannels = m_fifoAudioBus->numberOfChannels();
97
98     for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
99         float* destination = m_fifoAudioBus->channel(channelIndex)->mutableData();
100         const float* source = sourceBus->channel(channelIndex)->data();
101
102         bool isCopyGood = ((m_writeIndex < m_fifoLength)
103                            && (m_writeIndex + part1Length) <= m_fifoLength
104                            && part2Length < m_fifoLength
105                            && part1Length + part2Length <= sourceLength);
106         ASSERT(isCopyGood);
107         if (!isCopyGood)
108             return;
109
110         memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination));
111
112         // Handle wrap around of the FIFO, if needed.
113         if (part2Length)
114             memcpy(destination, source + part1Length, part2Length * sizeof(*destination));
115     }
116
117     m_framesInFifo += sourceLength;
118     ASSERT(m_framesInFifo <= m_fifoLength);
119     m_writeIndex = updateIndex(m_writeIndex, sourceLength);
120 }
121
122 void AudioFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length)
123 {
124     ASSERT_WITH_SECURITY_IMPLICATION(index < m_fifoLength && size <= m_fifoLength);
125     if (index < m_fifoLength && size <= m_fifoLength) {
126         if (index + size > m_fifoLength) {
127             // Need to wrap. Figure out the length of each piece.
128             part1Length = m_fifoLength - index;
129             part2Length = size - part1Length;
130         } else {
131             // No wrap needed.
132             part1Length = size;
133             part2Length = 0;
134         }
135     } else {
136         // Invalid values for index or size. Set the part lengths to zero so nothing is copied.
137         part1Length = 0;
138         part2Length = 0;
139     }
140 }
141
142 } // namespace blink
143
144 #endif // ENABLE(WEB_AUDIO)