/*
 * Copyright 2014 The Chromium Authors. All rights reserved.
 * Copyright (C) 2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "StereoPanner.h"

#if ENABLE(WEB_AUDIO)

#include "SharedBuffer.h"
#include "VectorMath.h"
#include <wtf/MathExtras.h>

namespace WebCore {

namespace StereoPanner {

void panWithSampleAccurateValues(const AudioBus* inputBus, AudioBus* outputBus, const float* panValues, size_t framesToProcess)
{
    bool isInputSafe = inputBus && (inputBus->numberOfChannels() == 1 || inputBus->numberOfChannels() == 2) && framesToProcess <= inputBus->length();
    ASSERT(isInputSafe);
    if (!isInputSafe)
        return;
    
    unsigned numberOfInputChannels = inputBus->numberOfChannels();
    
    bool isOutputSafe = outputBus && outputBus->numberOfChannels() == 2 && framesToProcess <= outputBus->length();
    ASSERT(isOutputSafe);
    if (!isOutputSafe)
        return;
    
    const float* sourceL = inputBus->channel(0)->data();
    const float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->data() : sourceL;
    float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutableData();
    float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->mutableData();
    
    if (!sourceL || !sourceR || !destinationL || !destinationR)
        return;
    
    double gainL;
    double gainR;
    double panRadian;
    
    int n = framesToProcess;
    
    // Handles mono source case first, then stereo source case.
    if (numberOfInputChannels == 1) {
        while (n--) {
            float inputL = *sourceL++;
            double pan = clampTo(*panValues++, -1.0, 1.0);
            // Pan from left to right [-1; 1] will be normalized as [0; 1].
            panRadian = (pan * 0.5 + 0.5) * piOverTwoDouble;
            gainL = cos(panRadian);
            gainR = sin(panRadian);
            *destinationL++ = static_cast<float>(inputL * gainL);
            *destinationR++ = static_cast<float>(inputL * gainR);
        }
    } else {
        while (n--) {
            float inputL = *sourceL++;
            float inputR = *sourceR++;
            double pan = clampTo(*panValues++, -1.0, 1.0);
            // Normalize [-1; 0] to [0; 1]. Do nothing when [0; 1].
            panRadian = (pan <= 0 ? pan + 1 : pan) * piOverTwoDouble;
            gainL = cos(panRadian);
            gainR = sin(panRadian);
            if (pan <= 0) {
                *destinationL++ = static_cast<float>(inputL + inputR * gainL);
                *destinationR++ = static_cast<float>(inputR * gainR);
            } else {
                *destinationL++ = static_cast<float>(inputL * gainL);
                *destinationR++ = static_cast<float>(inputR + inputL * gainR);
            }
        }
    }
}

void panToTargetValue(const AudioBus* inputBus, AudioBus* outputBus, float panValue, size_t framesToProcess)
{
    bool isInputSafe = inputBus && (inputBus->numberOfChannels() == 1 || inputBus->numberOfChannels() == 2) && framesToProcess <= inputBus->length();
    ASSERT(isInputSafe);
    if (!isInputSafe)
        return;
    
    unsigned numberOfInputChannels = inputBus->numberOfChannels();
    
    bool isOutputSafe = outputBus && outputBus->numberOfChannels() == 2 && framesToProcess <= outputBus->length();
    ASSERT(isOutputSafe);
    if (!isOutputSafe)
        return;
    
    const float* sourceL = inputBus->channel(0)->data();
    const float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->data() : sourceL;
    float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutableData();
    float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->mutableData();
    
    if (!sourceL || !sourceR || !destinationL || !destinationR)
        return;

    float targetPan = clampTo(panValue, -1.0, 1.0);
    
    if (numberOfInputChannels == 1) {
        double panRadian = (targetPan * 0.5 + 0.5) * piOverTwoDouble;
        
        double gainL = cos(panRadian);
        double gainR = sin(panRadian);
        
        VectorMath::multiplyByScalar(sourceL, gainL, destinationL, framesToProcess);
        VectorMath::multiplyByScalar(sourceL, gainR, destinationR, framesToProcess);
    } else {
        double panRadian = (targetPan <= 0 ? targetPan + 1 : targetPan) * piOverTwoDouble;
        
        double gainL = cos(panRadian);
        double gainR = sin(panRadian);

        if (targetPan <= 0) {
            VectorMath::multiplyByScalarThenAddToVector(sourceR, gainL, sourceL, destinationL, framesToProcess);
            VectorMath::multiplyByScalar(sourceR, gainR, destinationR, framesToProcess);
        } else {
            VectorMath::multiplyByScalar(sourceL, gainL, destinationL, framesToProcess);
            VectorMath::multiplyByScalarThenAddToVector(sourceL, gainR, sourceR, destinationR, framesToProcess);
        }
    }
}

} // namespace StereoPanner

} // namespace WebCore

#endif // ENABLE(WEB_AUDIO)
