/*
 * Copyright (C) 2010, Google Inc. All rights reserved.
 * Copyright (C) 2011 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.
 */

[
    ActiveDOMObject,
    Conditional=WEB_AUDIO,
    CustomToJSObject,
    EnabledBySetting=WebAudioEnabled,
    ExportMacro=WEBCORE_EXPORT,
    Exposed=Window
] interface BaseAudioContext : EventTarget {
    // All rendered audio ultimately connects to destination, which represents the audio hardware.
    readonly attribute AudioDestinationNode destination;

    // All scheduled times are relative to this time in seconds.
    readonly attribute double currentTime;

    // All AudioNodes in the context run at this sample-rate (sample-frames per second).
    readonly attribute float sampleRate;

    // All panning is relative to this listener.
    readonly attribute AudioListener listener;

    [SameObject, SecureContext] readonly attribute AudioWorklet audioWorklet;

    readonly attribute AudioContextState state;
    attribute EventHandler onstatechange;
    
    AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long numberOfFrames, float sampleRate);

    // Asynchronous audio file data decoding.
    Promise<AudioBuffer> decodeAudioData(ArrayBuffer audioData, optional AudioBufferCallback? successCallback, optional AudioBufferCallback? errorCallback);

    // Sources
    AudioBufferSourceNode createBufferSource();

    // Processing nodes
    GainNode createGain();
    DelayNode createDelay(optional double maxDelayTime = 1);
    BiquadFilterNode createBiquadFilter();
    WaveShaperNode createWaveShaper();
    PannerNode createPanner();
    ConvolverNode createConvolver();
    DynamicsCompressorNode createDynamicsCompressor();
    AnalyserNode createAnalyser();
    ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0, optional unsigned long numberOfInputChannels = 2, optional unsigned long numberOfOutputChannels = 2);
    OscillatorNode createOscillator();
    PeriodicWave createPeriodicWave(sequence<float> real, sequence<float> imag, optional PeriodicWaveOptions options);
    ConstantSourceNode createConstantSource();
    StereoPannerNode createStereoPanner();
    [CallWith=ScriptExecutionContext] IIRFilterNode createIIRFilter(sequence<double> feedforward, sequence<double> feedback);

    // Channel splitting and merging
    ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
    ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
};
