interface EventTarget {
  void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
  void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
  boolean dispatchEvent(Event event);
};

/*
callback interface EventListener {
  void handleEvent(Event event);
};
*/
// Callback interfaces are not supported yet, but that's ok
interface EventListener {};
callback DecodeErrorCallback = void (DOMException error);

callback DecodeSuccessCallback = void (AudioBuffer decodedData);

interface BaseAudioContext : EventTarget {
    readonly        attribute AudioDestinationNode destination;
    readonly        attribute float                sampleRate;
    readonly        attribute double               currentTime;
    readonly        attribute AudioListener        listener;
    readonly        attribute AudioContextState    state;
    readonly        attribute double               baseLatency;
    Promise          resume ();
                    attribute EventHandler         onstatechange;
    AudioBuffer            createBuffer (unsigned long numberOfChannels, unsigned long length, float sampleRate);
    Promise   decodeAudioData (ArrayBuffer audioData, optional DecodeSuccessCallback successCallback, optional DecodeErrorCallback errorCallback);
    AudioBufferSourceNode  createBufferSource ();
    ConstantSourceNode     createConstantSource ();
    ScriptProcessorNode    createScriptProcessor (optional unsigned long bufferSize = 0
              , optional unsigned long numberOfInputChannels = 2
              , optional unsigned long numberOfOutputChannels = 2
              );
    AnalyserNode           createAnalyser ();
    GainNode               createGain ();
    DelayNode              createDelay (optional double maxDelayTime);
    BiquadFilterNode       createBiquadFilter ();
    IIRFilterNode          createIIRFilter (sequence feedforward, sequence feedback);
    WaveShaperNode         createWaveShaper ();
    PannerNode             createPanner ();
    StereoPannerNode       createStereoPanner ();
    ConvolverNode          createConvolver ();
    ChannelSplitterNode    createChannelSplitter (optional unsigned long numberOfOutputs = 6
              );
    ChannelMergerNode      createChannelMerger (optional unsigned long numberOfInputs = 6
              );
    DynamicsCompressorNode createDynamicsCompressor ();
    OscillatorNode         createOscillator ();
    PeriodicWave           createPeriodicWave (Float32Array real, Float32Array imag, optional PeriodicWaveConstraints constraints);
};
enum ChannelCountMode {
    "max",
    "clamped-max",
    "explicit"
};

enum ChannelInterpretation {
    "speakers",
    "discrete"
};

interface AudioNode : EventTarget {

    void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
    void connect(AudioParam destination, optional unsigned long output = 0);
    void disconnect(optional unsigned long output = 0);

    readonly attribute BaseAudioContext context;
    readonly attribute unsigned long numberOfInputs;
    readonly attribute unsigned long numberOfOutputs;

    // Channel up-mixing and down-mixing rules for all inputs.
    attribute unsigned long channelCount;
    attribute ChannelCountMode channelCountMode;
    attribute ChannelInterpretation channelInterpretation;

};
interface AudioParam {

                    attribute float value;
    readonly        attribute float defaultValue;
    readonly        attribute float minValue;
    readonly        attribute float maxValue;

    // Parameter automation.
    void setValueAtTime(float value, double startTime);
    void linearRampToValueAtTime(float value, double endTime);
    void exponentialRampToValueAtTime(float value, double endTime);

    // Exponentially approach the target value with a rate having the given time constant.
    void setTargetAtTime(float target, double startTime, double timeConstant);

    // Sets an array of arbitrary parameter values starting at time for the given duration.
    // The number of values will be scaled to fit into the desired duration.
    void setValueCurveAtTime(Float32Array values, double startTime, double duration);

    // Cancels all scheduled parameter changes with times greater than or equal to startTime.
    void cancelScheduledValues(double startTime);

};
dictionary DelayOptions : AudioNodeOptions {
             double maxDelayTime = 1;
             double delayTime = 0;
};

[Constructor(BaseAudioContext context, optional DelayOptions options)]
interface DelayNode : AudioNode {

    readonly attribute AudioParam delayTime;

};