import { AudioParamBase, BaseAudioContext, context_, looksLikePath, native_, nativeCtor_, normalizeSourcePath, resolveLatencyHint, resolvePannerOptions } from './common';
const scratch_ = Symbol('[[scratch]]');
function spansEntireBuffer(data) {
    return data.byteOffset === 0 && data.byteLength === data.buffer.byteLength;
}
function getScratchBuffer(view) {
    const entry = view[scratch_];
    if (entry && entry.byteOffset === view.byteOffset && entry.byteLength === view.byteLength && entry.buffer.byteLength === view.byteLength) {
        return entry.buffer;
    }
    const buf = new ArrayBuffer(view.byteLength);
    try {
        Object.defineProperty(view, scratch_, {
            value: { byteOffset: view.byteOffset, byteLength: view.byteLength, buffer: buf },
            writable: true,
            configurable: true,
        });
    }
    catch (e) { }
    return buf;
}
function withWriteableNativeBuffer(data, call) {
    if (spansEntireBuffer(data)) {
        call(data.buffer);
        return;
    }
    const scratch = getScratchBuffer(data);
    call(scratch);
    const u8Src = new Uint8Array(scratch);
    const u8Dst = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
    u8Dst.set(u8Src);
}
function getReadableNativeBuffer(data) {
    if (spansEntireBuffer(data))
        return data.buffer;
    const scratch = getScratchBuffer(data);
    const u8Dst = new Uint8Array(scratch);
    const u8Src = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
    u8Dst.set(u8Src);
    return scratch;
}
function makeIOSHooks(native) {
    return {
        nativeSet(v) {
            native.setValue(v);
        },
        nativeScheduleSet(v, t) {
            native.setValueAtTime(v, t);
        },
        nativeScheduleLinearRamp(v, t) {
            native.linearRampToValueAtTime(v, t);
        },
        nativeCancel(t) {
            native.cancelScheduledValues(t);
        },
        nativeCancelAndHold(v, t) {
            native.cancelAndHoldAtTime(v, t);
        },
        nativeGetValue() {
            return native.value;
        },
        nativeSetAutomationRate(rate) {
            native.automationRate = rate;
        },
    };
}
export class AudioParam extends AudioParamBase {
    constructor(a, b) {
        if (a !== nativeCtor_ || !(b instanceof NSCAudioParam)) {
            throw new TypeError('Illegal constructor.');
        }
        super(makeIOSHooks(b), b.value);
        this[native_] = b;
    }
    get native() {
        return this[native_];
    }
}
export class AudioNode {
    constructor(context) {
        if (!(context instanceof BaseAudioContext)) {
            throw new TypeError(`${this.constructor.name} constructor: Argument 1 does not implement interface BaseAudioContext.`);
        }
        this[context_] = context;
    }
    get context() {
        return this[context_];
    }
    connect(node, output, input) {
        const that = this;
        const target = node?.native || node;
        try {
            if (typeof output === 'number' && typeof input === 'number')
                that.native.connectToOutputInput(target, output, input);
            else if (typeof output === 'number')
                that.native.connectToOutput(target, output);
            else
                that.native.connectTo(target);
        }
        catch (e) { }
    }
    disconnect(destinationOrOutput, output, input) {
        const that = this;
        try {
            if (!destinationOrOutput) {
                that.native.disconnect();
                return;
            }
            if (typeof destinationOrOutput === 'number') {
                try {
                    that.native.disconnectOutput(destinationOrOutput);
                }
                catch (e) {
                    that.native.disconnect();
                }
                return;
            }
            const dest = destinationOrOutput.native || destinationOrOutput;
            try {
                if (typeof output === 'number' && typeof input === 'number')
                    that.native.disconnectToOutputInput(dest, output, input);
                else if (typeof output === 'number')
                    that.native.disconnectToOutput(dest, output);
                else
                    that.native.disconnectTo(dest);
            }
            catch (e) {
                try {
                    that.native.disconnect();
                }
                catch (ee) { }
            }
        }
        catch (e) { }
    }
}
export class AudioBuffer {
    constructor(options, buffer) {
        if (!options)
            throw new TypeError('AudioBuffer constructor requires options');
        if (options === nativeCtor_ && buffer instanceof NSCAudioBuffer) {
            this[native_] = buffer;
        }
        else {
            const opts = options;
            const length = Math.max(0, opts.length | 0);
            const ch = opts.numberOfChannels != null ? Math.max(1, opts.numberOfChannels | 0) : 1;
            const sr = opts.sampleRate != null ? opts.sampleRate : 48000;
            this[native_] = NSCAudioBuffer.alloc().initWithLengthNumberOfChannelsSampleRate(length, ch, sr);
        }
    }
    get native() {
        return this[native_];
    }
    get sampleRate() {
        return this.native.sampleRate;
    }
    get length() {
        return this.native.length;
    }
    get duration() {
        return this.native.duration;
    }
    get numberOfChannels() {
        return this.native.numberOfChannels;
    }
    getChannelData(channel) {
        const nsdata = this.native.getChannelData(channel);
        if (nsdata) {
            const buf = interop.bufferFromData(nsdata);
            if (buf)
                return new Float32Array(buf);
        }
        return null;
    }
    copyFromChannel(dest, channel, startInChannel = 0) {
        if (!dest)
            return;
        const native = this.native;
        const start = startInChannel ?? 0;
        withWriteableNativeBuffer(dest, (raw) => native.copyFromChannel(raw, channel, start));
    }
    copyToChannel(source, channel, startInChannel = 0) {
        if (!source)
            return;
        this.native.copyToChannel(getReadableNativeBuffer(source), channel, startInChannel ?? 0);
    }
}
export class GainNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        this._native = context.native.createGainNode();
        this._initialGain = typeof options?.gain === 'number' ? options.gain : (this._native.gain ?? 1);
    }
    get native() {
        return this._native;
    }
    get gain() {
        if (!this._gainParam) {
            const gain = this._native.gainParam;
            if (this._initialGain !== 1)
                gain.setValue(this._initialGain);
            this._gainParam = new AudioParam(nativeCtor_, gain);
        }
        return this._gainParam;
    }
}
export class BiquadFilterNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        const initialFreq = typeof options?.frequency === 'number' ? options.frequency : 440;
        const initialQ = typeof options?.Q === 'number' ? options.Q : 1.0;
        const initialGain = typeof options?.gain === 'number' ? options.gain : 0.0;
        this[native_] = context.native.createBiquadNodeFrequencyQGain(options.type ?? 'lowpass', initialFreq, initialQ, initialGain);
    }
    get native() {
        return this[native_];
    }
    get frequency() {
        if (!this._frequencyParam)
            this._frequencyParam = new AudioParam(nativeCtor_, this.native.frequencyParam);
        return this._frequencyParam;
    }
    get Q() {
        if (!this._qParam)
            this._qParam = new AudioParam(nativeCtor_, this.native.qParam);
        return this._qParam;
    }
    get gain() {
        if (!this._gainParam)
            this._gainParam = new AudioParam(nativeCtor_, this.native.gainParam);
        return this._gainParam;
    }
    get detune() {
        if (!this._detuneParam)
            this._detuneParam = new AudioParam(nativeCtor_, this.native.detuneParam);
        return this._detuneParam;
    }
    set type(v) {
        this.native.setType(v);
    }
    get type() {
        return this.native.getType();
    }
}
export class PannerNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        const p = resolvePannerOptions(options);
        this[native_] = NSCAudioPannerNode.alloc().initWithContextAndParams(context.native, p.positionX, p.positionY, p.positionZ, p.orientationX, p.orientationY, p.orientationZ, p.pan, p.distanceModel, p.panningModel, p.refDistance, p.maxDistance, p.rolloffFactor, p.coneInnerAngle, p.coneOuterAngle, p.coneOuterGain);
    }
    get native() {
        return this[native_];
    }
    get positionX() {
        return this._positionX || (this._positionX = new AudioParam(nativeCtor_, this.native.positionXParam));
    }
    get positionY() {
        return this._positionY || (this._positionY = new AudioParam(nativeCtor_, this.native.positionYParam));
    }
    get positionZ() {
        return this._positionZ || (this._positionZ = new AudioParam(nativeCtor_, this.native.positionZParam));
    }
    get orientationX() {
        return this._orientationX || (this._orientationX = new AudioParam(nativeCtor_, this.native.orientationXParam));
    }
    get orientationY() {
        return this._orientationY || (this._orientationY = new AudioParam(nativeCtor_, this.native.orientationYParam));
    }
    get orientationZ() {
        return this._orientationZ || (this._orientationZ = new AudioParam(nativeCtor_, this.native.orientationZParam));
    }
    get distanceModel() {
        return this.native.getDistanceModel();
    }
    set distanceModel(v) {
        this.native.setDistanceModel(v);
    }
    get panningModel() {
        return this.native.getPanningModel();
    }
    set panningModel(v) {
        this.native.setPanningModel(v);
    }
    get refDistance() {
        return this.native.getRefDistance();
    }
    set refDistance(v) {
        this.native.setRefDistance(v);
    }
    get maxDistance() {
        return this.native.getMaxDistance();
    }
    set maxDistance(v) {
        this.native.setMaxDistance(v);
    }
    get rolloffFactor() {
        return this.native.getRolloffFactor();
    }
    set rolloffFactor(v) {
        this.native.setRolloffFactor(v);
    }
    get coneInnerAngle() {
        return this.native.getConeInnerAngle();
    }
    set coneInnerAngle(v) {
        this.native.setConeInnerAngle(v);
    }
    get coneOuterAngle() {
        return this.native.getConeOuterAngle();
    }
    set coneOuterAngle(v) {
        this.native.setConeOuterAngle(v);
    }
    get coneOuterGain() {
        return this.native.getConeOuterGain();
    }
    set coneOuterGain(v) {
        this.native.setConeOuterGain(v);
    }
    setPosition(x, y, z) {
        this.native.setPosition(x, y, z);
    }
    setOrientation(x, y, z) {
        this.native.setOrientation(x, y, z);
    }
}
export class AudioDestinationNode extends AudioNode {
    constructor(context, node) {
        super(context);
        if (!(node instanceof NSCAudioNode))
            throw new TypeError('Illegal constructor.');
        this[native_] = node;
    }
    get native() {
        return this[native_];
    }
}
export class AudioScheduledSourceNode extends AudioNode {
    constructor(context, node) {
        super(context);
        if (!(node instanceof NSCAudioScheduledSourceNode))
            throw new TypeError('Illegal constructor.');
        this[native_] = node;
    }
    get native() {
        return this[native_];
    }
    start() {
        this.native.start();
    }
    stop() {
        this.native.stop();
    }
}
export class OscillatorNode extends AudioScheduledSourceNode {
    constructor(context, options = {}) {
        const type = options?.type || 'sine';
        const freq = options?.frequency || 440;
        super(context, context.native.createOscillatorNodeFrequency(type, freq));
    }
    get native() {
        return this[native_];
    }
    get frequency() {
        if (!this._frequencyParam)
            this._frequencyParam = new AudioParam(nativeCtor_, this.native.frequencyParam);
        return this._frequencyParam;
    }
    setPeriodicWave(wave) {
        if (!wave)
            return;
        this.native.setPeriodicWave(wave.native);
    }
}
class SideEffectAudioParam extends AudioParamBase {
    constructor(nsc, apply) {
        super({
            nativeSet(v) {
                nsc.setValue(v);
                apply(v);
            },
            nativeScheduleSet(v, t) {
                nsc.setValueAtTime(v, t);
                apply(v);
            },
            nativeScheduleLinearRamp(v, t) {
                nsc.linearRampToValueAtTime(v, t);
                apply(v);
            },
            nativeCancel(t) {
                nsc.cancelScheduledValues(t);
            },
            nativeCancelAndHold(v, t) {
                nsc.cancelAndHoldAtTime(v, t);
                apply(v);
            },
            nativeGetValue() {
                return nsc.value;
            },
            nativeSetAutomationRate(rate) {
                nsc.automationRate = rate;
            },
        }, nsc.value);
    }
}
export class StereoPannerNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        const pan = typeof options.pan === 'number' ? options.pan : 0;
        this[native_] = context.native.createStereoPannerNode(pan);
    }
    get native() {
        return this[native_];
    }
    get pan() {
        if (!this._panParam)
            this._panParam = new AudioParam(nativeCtor_, this.native.panParam);
        return this._panParam;
    }
}
export class DelayNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        this._delayTimeParam = null;
        const delay = typeof options.delayTime === 'number' ? options.delayTime : 0;
        const max = typeof options.maxDelayTime === 'number' ? options.maxDelayTime : 1.0;
        this[native_] = context.native.createDelayNodeMaxDelayTime(delay, max);
    }
    get native() {
        return this[native_];
    }
    get delayTime() {
        if (!this._delayTimeParam) {
            const n = this.native;
            this._delayTimeParam = new AudioParam(nativeCtor_, n.delayTimeParam);
        }
        return this._delayTimeParam;
    }
    get maxDelayTime() {
        return this.native.maxDelayTime;
    }
}
export class ConstantSourceNode extends AudioScheduledSourceNode {
    constructor(context, options = {}) {
        const offset = typeof options.offset === 'number' ? options.offset : 1.0;
        super(context, context.native.createConstantSourceNode(offset));
        this._offsetParam = null;
    }
    get native() {
        return this[native_];
    }
    get offset() {
        if (!this._offsetParam) {
            const n = this.native;
            this._offsetParam = new AudioParam(nativeCtor_, n.offsetParam);
        }
        return this._offsetParam;
    }
}
export class AnalyserNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        this[native_] = context.native.createAnalyserNode();
        if (typeof options.fftSize === 'number')
            this.native.fftSize = options.fftSize;
        if (typeof options.smoothingTimeConstant === 'number')
            this.native.smoothingTimeConstant = options.smoothingTimeConstant;
        if (typeof options.minDecibels === 'number')
            this.native.minDecibels = options.minDecibels;
        if (typeof options.maxDecibels === 'number')
            this.native.maxDecibels = options.maxDecibels;
    }
    get native() {
        return this[native_];
    }
    get fftSize() {
        return this.native.fftSize;
    }
    set fftSize(v) {
        this.native.fftSize = v;
    }
    get frequencyBinCount() {
        return this.native.frequencyBinCount;
    }
    get smoothingTimeConstant() {
        return this.native.smoothingTimeConstant;
    }
    set smoothingTimeConstant(v) {
        this.native.smoothingTimeConstant = v;
    }
    get minDecibels() {
        return this.native.minDecibels;
    }
    set minDecibels(v) {
        this.native.minDecibels = v;
    }
    get maxDecibels() {
        return this.native.maxDecibels;
    }
    set maxDecibels(v) {
        this.native.maxDecibels = v;
    }
    getFloatTimeDomainData(dest) {
        if (!dest || dest.length === 0)
            return;
        const native = this.native;
        withWriteableNativeBuffer(dest, (raw) => native.getFloatTimeDomainData(raw));
    }
    getByteTimeDomainData(dest) {
        if (!dest || dest.length === 0)
            return;
        const native = this.native;
        withWriteableNativeBuffer(dest, (raw) => native.getByteTimeDomainData(raw));
    }
    getFloatFrequencyData(dest) {
        if (!dest || dest.length === 0)
            return;
        const native = this.native;
        withWriteableNativeBuffer(dest, (raw) => native.getFloatFrequencyData(raw));
    }
    getByteFrequencyData(dest) {
        if (!dest || dest.length === 0)
            return;
        const native = this.native;
        if (dest instanceof NSMutableData) {
            native.getByteFrequencyData(dest);
            return;
        }
        withWriteableNativeBuffer(dest, (raw) => native.getByteFrequencyData(raw));
    }
}
export class WaveShaperNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        this._curve = null;
        this[native_] = context.native.createWaveShaperNode();
        if (options.curve)
            this.curve = options.curve instanceof Float32Array ? options.curve : Float32Array.from(options.curve);
        if (options.oversample)
            this.oversample = options.oversample;
    }
    get native() {
        return this[native_];
    }
    get curve() {
        return this._curve;
    }
    set curve(v) {
        this._curve = v;
        if (!v) {
            this.native.setCurveFromData(null);
            return;
        }
        this.native.setCurveFromData(getReadableNativeBuffer(v));
    }
    get oversample() {
        return this.native.oversample;
    }
    set oversample(v) {
        this.native.oversample = v;
    }
}
export class IIRFilterNode extends AudioNode {
    constructor(context, options) {
        super(context);
        const ff = options?.feedforward ?? [];
        const fb = options?.feedback ?? [];
        if (!ff.length || !fb.length)
            throw new TypeError('IIRFilterNode: feedforward and feedback are required');
        this[native_] = context.native.createIIRFilterNodeFeedback(ff, fb);
    }
    get native() {
        return this[native_];
    }
    getFrequencyResponse(frequencyHz, magResponse, phaseResponse) {
        if (!frequencyHz || !magResponse || !phaseResponse)
            return;
        const hz = getReadableNativeBuffer(frequencyHz);
        const native = this.native;
        withWriteableNativeBuffer(magResponse, (mag) => {
            withWriteableNativeBuffer(phaseResponse, (phase) => {
                native.getFrequencyResponseMagResponsePhaseResponse(hz, mag, phase);
            });
        });
    }
}
export class ConvolverNode extends AudioNode {
    constructor(context, options = {}) {
        super(context);
        this[native_] = context.native.createConvolverNode();
        this.native.normalize = !options.disableNormalization;
    }
    get native() {
        return this[native_];
    }
    get buffer() {
        const b = this.native.buffer;
        return b ? new AudioBuffer(nativeCtor_, b) : null;
    }
    set buffer(v) {
        this.native.buffer = v?.native ?? null;
    }
    get normalize() {
        return this.native.normalize;
    }
    set normalize(v) {
        this.native.normalize = v;
    }
}
export class PeriodicWave {
    constructor(_context, options = {}) {
        const real = options.real ? (options.real instanceof Float32Array ? options.real : Float32Array.from(options.real)) : new Float32Array(2);
        const imag = options.imag ? (options.imag instanceof Float32Array ? options.imag : Float32Array.from(options.imag)) : new Float32Array(real.length);
        const realData = getReadableNativeBuffer(real);
        const imagData = getReadableNativeBuffer(imag);
        this[native_] = NSCPeriodicWave.alloc().initWithRealImagDisableNormalization(realData, imagData, !!options.disableNormalization);
    }
    get native() {
        return this[native_];
    }
}
export class AudioBufferSourceNode extends AudioScheduledSourceNode {
    constructor(context, options = {}) {
        const param = options?.buffer != null ? options.buffer.native : null;
        super(context, context.native.createBufferSourceNode(param));
    }
    get native() {
        return this[native_];
    }
    set loop(v) {
        this.native.loop = v;
    }
    get loop() {
        return this.native.loop;
    }
    get buffer() {
        const b = this.native.buffer;
        return b ? new AudioBuffer(nativeCtor_, b) : null;
    }
    set buffer(v) {
        this.native.buffer = v?.native ?? null;
    }
}
export class AudioContext extends BaseAudioContext {
    constructor(options) {
        super();
        this._destination = null;
        const sampleRate = options?.sampleRate ?? 48000;
        const latencyHint = resolveLatencyHint(options?.latencyHint);
        this[native_] = NSCAudioContext.alloc().initWithSampleRateLatencyHint(sampleRate, latencyHint);
        try {
            const nd = this[native_].destination;
            this._destination = nd ? new AudioDestinationNode(this, nd) : null;
        }
        catch (e) {
            this._destination = null;
        }
    }
    get destination() {
        return this._destination;
    }
    createGain(options) {
        return new GainNode(this, options ?? {});
    }
    createBiquad(options) {
        return new BiquadFilterNode(this, options ?? {});
    }
    createPanner(options) {
        return new PannerNode(this, options ?? {});
    }
    createOscillator(options) {
        return new OscillatorNode(this, options ?? {});
    }
    createBuffer(options) {
        return new AudioBuffer(options);
    }
    createBufferSource(options) {
        return new AudioBufferSourceNode(this, options ?? {});
    }
    createStereoPanner(options) {
        return new StereoPannerNode(this, options ?? {});
    }
    createDelay(options) {
        return new DelayNode(this, options ?? {});
    }
    createConstantSource(options) {
        return new ConstantSourceNode(this, options ?? {});
    }
    createAnalyser(options) {
        return new AnalyserNode(this, options ?? {});
    }
    createWaveShaper(options) {
        return new WaveShaperNode(this, options ?? {});
    }
    createIIRFilter(feedforward, feedback) {
        return new IIRFilterNode(this, { feedforward, feedback });
    }
    createConvolver(options) {
        return new ConvolverNode(this, options ?? {});
    }
    createPeriodicWave(real, imag, options) {
        return new PeriodicWave(this, { real, imag, disableNormalization: options?.disableNormalization });
    }
    get native() {
        return this[native_];
    }
    get sampleRate() {
        return this.native.sampleRate;
    }
    get currentTime() {
        return this.native.currentTime;
    }
    resume() {
        this.native.resume();
        return Promise.resolve();
    }
    suspend() {
        this.native.suspend();
        return Promise.resolve();
    }
    close() {
        this[native_] = null;
        this._destination = null;
        return Promise.resolve();
    }
    get sinkId() {
        try {
            return this.native.currentSinkId();
        }
        catch (e) {
            return 'default';
        }
    }
    setSinkId(deviceId) {
        return new Promise((resolve, reject) => {
            try {
                const ok = this.native.setSinkId(deviceId ?? 'default');
                if (ok)
                    resolve();
                else
                    reject(new DOMException(`setSinkId(${deviceId}) rejected by AVAudioSession`, 'NotFoundError'));
            }
            catch (e) {
                reject(e);
            }
        });
    }
    decodeAudioData(source) {
        return new Promise((resolve, reject) => {
            try {
                if (typeof source === 'string') {
                    if (looksLikePath(source)) {
                        const filePath = normalizeSourcePath(source);
                        this.native.decodeAudioDataFromFileAsync(filePath, (wrapper) => {
                            if (!wrapper)
                                return reject(new Error('decodeAudioData failed'));
                            resolve(new AudioBuffer(nativeCtor_, wrapper));
                        });
                        return;
                    }
                    this.native.decodeAudioDataAsync(source, (wrapper) => {
                        if (!wrapper)
                            return reject(new Error('decodeAudioData failed'));
                        resolve(new AudioBuffer(nativeCtor_, wrapper));
                    });
                    return;
                }
                this.native.decodeAudioDataFromDataAsync(source, (wrapper) => {
                    if (!wrapper)
                        return reject(new Error('decodeAudioData failed'));
                    resolve(new AudioBuffer(nativeCtor_, wrapper));
                });
            }
            catch (e) {
                reject(e);
            }
        });
    }
}
export class OfflineAudioContext extends BaseAudioContext {
    constructor(numberOfChannels, lengthInFrames, sampleRate) {
        super();
        this.destination = null;
        this[native_] = NSCOfflineAudioContext.new();
        this[native_].configure(numberOfChannels, lengthInFrames, sampleRate);
        try {
            const nd = this[native_].destination;
            this.destination = nd ? new AudioDestinationNode(this, nd) : null;
        }
        catch (e) {
            this.destination = null;
        }
    }
    get native() {
        return this[native_];
    }
    createGain(options) {
        return new GainNode(this, options ?? {});
    }
    createBiquad(options) {
        return new BiquadFilterNode(this, options ?? {});
    }
    createPanner(options) {
        return new PannerNode(this, options ?? {});
    }
    createOscillator(options) {
        return new OscillatorNode(this, options ?? {});
    }
    createBufferSource(options) {
        return new AudioBufferSourceNode(this, options ?? {});
    }
    createStereoPanner(options) {
        return new StereoPannerNode(this, options ?? {});
    }
    createDelay(options) {
        return new DelayNode(this, options ?? {});
    }
    createConstantSource(options) {
        return new ConstantSourceNode(this, options ?? {});
    }
    createAnalyser(options) {
        return new AnalyserNode(this, options ?? {});
    }
    createWaveShaper(options) {
        return new WaveShaperNode(this, options ?? {});
    }
    createIIRFilter(feedforward, feedback) {
        return new IIRFilterNode(this, { feedforward, feedback });
    }
    createConvolver(options) {
        return new ConvolverNode(this, options ?? {});
    }
    createPeriodicWave(real, imag, options) {
        return new PeriodicWave(this, { real, imag, disableNormalization: options?.disableNormalization });
    }
    decodeAudioData(source) {
        return new Promise((resolve, reject) => {
            try {
                if (typeof source === 'string') {
                    if (looksLikePath(source)) {
                        const filePath = normalizeSourcePath(source);
                        this.native.decodeAudioDataFromFileAsyncOffline(filePath, (wrapper) => {
                            if (!wrapper)
                                return reject(new Error('decodeAudioData failed'));
                            resolve(new AudioBuffer(nativeCtor_, wrapper));
                        });
                        return;
                    }
                    this.native.decodeAudioDataAsync(source, (wrapper) => {
                        if (!wrapper)
                            return reject(new Error('decodeAudioData failed'));
                        resolve(new AudioBuffer(nativeCtor_, wrapper));
                    });
                    return;
                }
                this.native.decodeAudioDataFromDataAsyncOffline(source, (wrapper) => {
                    if (!wrapper)
                        return reject(new Error('decodeAudioData failed'));
                    resolve(new AudioBuffer(nativeCtor_, wrapper));
                });
            }
            catch (e) {
                reject(e);
            }
        });
    }
    startRendering() {
        return new Promise((resolve, reject) => {
            this.native.startRenderingAsync((wrapper) => {
                if (!wrapper)
                    return reject(new Error('startRendering failed'));
                resolve(new AudioBuffer(nativeCtor_, wrapper));
            });
        });
    }
}
//# sourceMappingURL=index.ios.js.map