15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * its contributors may be used to endorse or promote products derived 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * from this software without specific prior written permission. 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(WEB_AUDIO) 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/AudioFIFO.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)AudioFIFO::AudioFIFO(unsigned numberOfChannels, size_t fifoLength) 3881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) : m_fifoAudioBus(AudioBus::create(numberOfChannels, fifoLength)) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_fifoLength(fifoLength) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_framesInFifo(0) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_readIndex(0) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_writeIndex(0) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioFIFO::consume(AudioBus* destination, size_t framesToConsume) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isGood = destination && (framesToConsume <= m_fifoLength) && (framesToConsume <= m_framesInFifo) && (destination->length() >= framesToConsume); 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isGood); 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isGood) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Copy the requested number of samples to the destination. 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t part1Length; 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t part2Length; 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length); 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) size_t numberOfChannels = m_fifoAudioBus->numberOfChannels(); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* destinationData = destination->channel(channelIndex)->mutableData(); 6381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) const float* sourceData = m_fifoAudioBus->channel(channelIndex)->data(); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isCopyGood = ((m_readIndex < m_fifoLength) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && (m_readIndex + part1Length) <= m_fifoLength 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && (part1Length <= destination->length()) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && (part1Length + part2Length) <= destination->length()); 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isCopyGood); 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isCopyGood) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData)); 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle wrap around of the FIFO, if needed. 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (part2Length) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData)); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_readIndex = updateIndex(m_readIndex, framesToConsume); 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_framesInFifo >= framesToConsume); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_framesInFifo -= framesToConsume; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioFIFO::push(const AudioBus* sourceBus) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Copy the sourceBus into the FIFO buffer. 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isGood = sourceBus && (m_framesInFifo + sourceBus->length() <= m_fifoLength); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isGood) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t sourceLength = sourceBus->length(); 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t part1Length; 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t part2Length; 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) findWrapLengths(m_writeIndex, sourceLength, part1Length, part2Length); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) size_t numberOfChannels = m_fifoAudioBus->numberOfChannels(); 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { 9981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) float* destination = m_fifoAudioBus->channel(channelIndex)->mutableData(); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const float* source = sourceBus->channel(channelIndex)->data(); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isCopyGood = ((m_writeIndex < m_fifoLength) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && (m_writeIndex + part1Length) <= m_fifoLength 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && part2Length < m_fifoLength 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && part1Length + part2Length <= sourceLength); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isCopyGood); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isCopyGood) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination)); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle wrap around of the FIFO, if needed. 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (part2Length) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(destination, source + part1Length, part2Length * sizeof(*destination)); 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 11602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_framesInFifo += sourceLength; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_framesInFifo <= m_fifoLength); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_writeIndex = updateIndex(m_writeIndex, sourceLength); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length) 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ASSERT_WITH_SECURITY_IMPLICATION(index < m_fifoLength && size <= m_fifoLength); 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (index < m_fifoLength && size <= m_fifoLength) { 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (index + size > m_fifoLength) { 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Need to wrap. Figure out the length of each piece. 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) part1Length = m_fifoLength - index; 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) part2Length = size - part1Length; 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // No wrap needed. 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) part1Length = size; 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) part2Length = 0; 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Invalid values for index or size. Set the part lengths to zero so nothing is copied. 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) part1Length = 0; 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) part2Length = 0; 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 142c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(WEB_AUDIO) 145