//
// Copyright 2022-2023 Picovoice Inc.
//
// You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
// file accompanying this source.
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const pv_recorder_status_t_1 = require("./pv_recorder_status_t");
const errors_1 = require("./errors");
const platforms_1 = require("./platforms");
/**
 * PvRecorder class for recording audio.
 */
class PvRecorder {
    // eslint-disable-next-line
    static _pvRecorder = require((0, platforms_1.getSystemLibraryPath)());
    _handle;
    _frameLength;
    _sampleRate;
    _version;
    /**
     * PvRecorder constructor.
     *
     * @param frameLength Length of the audio frames to receive per read call.
     * @param deviceIndex The audio device index to use to record audio. A value of (-1) will use machine's default audio device.
     * @param bufferedFramesCount The number of audio frames buffered internally for reading - i.e. internal circular buffer
     * will be of size `frameLength` * `bufferedFramesCount`. If this value is too low, buffer overflows could occur
     * and audio frames could be dropped. A higher value will increase memory usage.
     */
    constructor(frameLength, deviceIndex = -1, bufferedFramesCount = 50) {
        let pvRecorderHandleAndStatus;
        try {
            pvRecorderHandleAndStatus = PvRecorder._pvRecorder.init(frameLength, deviceIndex, bufferedFramesCount);
        }
        catch (err) {
            (0, errors_1.default)(err.code, err);
        }
        const status = pvRecorderHandleAndStatus.status;
        if (status !== pv_recorder_status_t_1.default.SUCCESS) {
            throw (0, errors_1.default)(status, "PvRecorder failed to initialize.");
        }
        this._handle = pvRecorderHandleAndStatus.handle;
        this._frameLength = frameLength;
        this._sampleRate = PvRecorder._pvRecorder.sample_rate();
        this._version = PvRecorder._pvRecorder.version();
    }
    /**
     * @returns Length of the audio frames to receive per read call.
     */
    get frameLength() {
        return this._frameLength;
    }
    /**
     * @returns Audio sample rate used by PvRecorder.
     */
    get sampleRate() {
        return this._sampleRate;
    }
    /**
     * @returns the version of the PvRecorder
     */
    get version() {
        return this._version;
    }
    /**
     * @returns Whether PvRecorder is currently recording audio or not.
     */
    get isRecording() {
        return PvRecorder._pvRecorder.get_is_recording(this._handle);
    }
    /**
     * Starts recording audio.
     */
    start() {
        const status = PvRecorder._pvRecorder.start(this._handle);
        if (status !== pv_recorder_status_t_1.default.SUCCESS) {
            throw (0, errors_1.default)(status, "PvRecorder failed to start.");
        }
    }
    /**
     * Stops recording audio.
     */
    stop() {
        const status = PvRecorder._pvRecorder.stop(this._handle);
        if (status !== pv_recorder_status_t_1.default.SUCCESS) {
            throw (0, errors_1.default)(status, "PvRecorder failed to stop.");
        }
    }
    /**
     * Asynchronous call to read a frame of audio data.
     *
     * @returns {Promise<Int16Array>} Audio data frame.
     */
    async read() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                const pcm = new Int16Array(this._frameLength);
                const status = PvRecorder._pvRecorder.read(this._handle, pcm);
                if (status !== pv_recorder_status_t_1.default.SUCCESS) {
                    reject((0, errors_1.default)(status, "PvRecorder failed to read audio data frame."));
                }
                resolve(pcm);
            });
        });
    }
    /**
     * Synchronous call to read a frame of audio data.
     *
     * @returns {Int16Array} Audio data frame.
     */
    readSync() {
        const pcm = new Int16Array(this._frameLength);
        const status = PvRecorder._pvRecorder.read(this._handle, pcm);
        if (status !== pv_recorder_status_t_1.default.SUCCESS) {
            throw (0, errors_1.default)(status, "PvRecorder failed to read audio data frame.");
        }
        return pcm;
    }
    /**
     * Enable or disable debug logging for PvRecorder. Debug logs will indicate when there are overflows in the internal
     * frame buffer and when an audio source is generating frames of silence.
     *
     * @param isDebugLoggingEnabled Boolean indicating whether the debug logging is enabled or disabled.
     */
    setDebugLogging(isDebugLoggingEnabled) {
        PvRecorder._pvRecorder.set_debug_logging(this._handle, isDebugLoggingEnabled);
    }
    /**
     * Returns the name of the selected device used to capture audio.
     *
     * @returns {string} Name of the selected audio device.
     */
    getSelectedDevice() {
        const device = PvRecorder._pvRecorder.get_selected_device(this._handle);
        if ((device === undefined) || (device === null)) {
            throw new Error("Failed to get selected device.");
        }
        return device;
    }
    /**
     * Destructor. Releases resources acquired by PvRecorder.
     */
    release() {
        PvRecorder._pvRecorder.delete(this._handle);
    }
    /**
     * Helper function to get the list of available audio devices.
     *
     * @returns {Array<string>} An array of the available device names.
     */
    static getAvailableDevices() {
        const devices = PvRecorder._pvRecorder.get_available_devices();
        if ((devices === undefined) || (devices === null)) {
            throw new Error("Failed to get audio devices.");
        }
        return devices;
    }
}
exports.default = PvRecorder;
//# sourceMappingURL=pv_recorder.js.map