15ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/*
25ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * Copyright (C) 2010 Google Inc. All rights reserved.
35ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *
45ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * Redistribution and use in source and binary forms, with or without
55ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * modification, are permitted provided that the following conditions
65ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * are met:
75ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *
85ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * 1.  Redistributions of source code must retain the above copyright
95ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *     notice, this list of conditions and the following disclaimer.
105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * 2.  Redistributions in binary form must reproduce the above copyright
115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *     notice, this list of conditions and the following disclaimer in the
125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *     documentation and/or other materials provided with the distribution.
135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *     its contributors may be used to endorse or promote products derived
155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *     from this software without specific prior written permission.
165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen *
175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen */
285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "config.h"
305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#if ENABLE(WEB_AUDIO)
325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "ReverbAccumulationBuffer.h"
345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
35e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "VectorMath.h"
365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsennamespace WebCore {
385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
39e14391e94c850b8bd03680c23b38978db68687a8John Reckusing namespace VectorMath;
40e14391e94c850b8bd03680c23b38978db68687a8John Reck
415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenReverbAccumulationBuffer::ReverbAccumulationBuffer(size_t length)
425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    : m_buffer(length)
435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    , m_readIndex(0)
445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    , m_readTimeFrame(0)
455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid ReverbAccumulationBuffer::readAndClear(float* destination, size_t numberOfFrames)
495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t bufferLength = m_buffer.size();
515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    bool isCopySafe = m_readIndex <= bufferLength && numberOfFrames <= bufferLength;
525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    ASSERT(isCopySafe);
545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (!isCopySafe)
555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return;
565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t framesAvailable = bufferLength - m_readIndex;
585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t numberOfFrames1 = std::min(numberOfFrames, framesAvailable);
595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t numberOfFrames2 = numberOfFrames - numberOfFrames1;
605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    float* source = m_buffer.data();
625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    memcpy(destination, source + m_readIndex, sizeof(float) * numberOfFrames1);
635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    memset(source + m_readIndex, 0, sizeof(float) * numberOfFrames1);
645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // Handle wrap-around if necessary
665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (numberOfFrames2 > 0) {
675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        memcpy(destination + numberOfFrames1, source, sizeof(float) * numberOfFrames2);
685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        memset(source, 0, sizeof(float) * numberOfFrames2);
695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    m_readIndex = (m_readIndex + numberOfFrames) % bufferLength;
725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    m_readTimeFrame += numberOfFrames;
735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid ReverbAccumulationBuffer::updateReadIndex(int* readIndex, size_t numberOfFrames) const
765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // Update caller's readIndex
785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    *readIndex = (*readIndex + numberOfFrames) % m_buffer.size();
795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenint ReverbAccumulationBuffer::accumulate(float* source, size_t numberOfFrames, int* readIndex, size_t delayFrames)
825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t bufferLength = m_buffer.size();
845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t writeIndex = (*readIndex + delayFrames) % bufferLength;
865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // Update caller's readIndex
885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    *readIndex = (*readIndex + numberOfFrames) % bufferLength;
895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t framesAvailable = bufferLength - writeIndex;
915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t numberOfFrames1 = std::min(numberOfFrames, framesAvailable);
925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    size_t numberOfFrames2 = numberOfFrames - numberOfFrames1;
935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    float* destination = m_buffer.data();
955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    bool isSafe = writeIndex <= bufferLength && numberOfFrames1 + writeIndex <= bufferLength && numberOfFrames2 <= bufferLength;
975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    ASSERT(isSafe);
985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (!isSafe)
995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 0;
1005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    vadd(source, 1, destination + writeIndex, 1, destination + writeIndex, 1, numberOfFrames1);
1025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // Handle wrap-around if necessary
1045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (numberOfFrames2 > 0)
1055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        vadd(source + numberOfFrames1, 1, destination, 1, destination, 1, numberOfFrames2);
1065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    return writeIndex;
1085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid ReverbAccumulationBuffer::reset()
1115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    m_buffer.zero();
1135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    m_readIndex = 0;
1145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    m_readTimeFrame = 0;
1155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen} // namespace WebCore
1185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#endif // ENABLE(WEB_AUDIO)
120