export default class Microphone
{
    #FFT_SIZE = 512;

    constructor()
    {
        this.initialized = false;

        navigator.mediaDevices.getUserMedia({
            audio: true
        })
            .then(mediaStream => {
                this.mediaStream = mediaStream;
                this.audioContext = new AudioContext();
                this.microphone = this.audioContext.createMediaStreamSource(mediaStream);
                this.analyzer = this.audioContext.createAnalyser();
                this.analyzer.fftSize = this.#FFT_SIZE;

                const bufferLength = this.analyzer.frequencyBinCount;
                this.dataArray = new Uint8Array(bufferLength);
                this.microphone.connect(this.analyzer);
                this.initialized = true;
            })
            .catch(error => {
                throw new Error(error);
            });
    }

    stopMediaStream()
    {
        this.mediaStream?.getTracks().forEach((track) => {
            track.stop();
        });
    }

    getSamples()
    {
        this.analyzer?.getByteTimeDomainData(this.dataArray);

        return [...this.dataArray].map(element => element/128 - 1);
    }

    getVolume()
    {
        this.analyzer?.getByteTimeDomainData(this.dataArray);
        let normalSamples = [...this.dataArray].map(element => element/128 - 1);

        let sampleSum = 0;
        normalSamples.forEach((normalSample, index) => {
            sampleSum += normalSample[index] * normalSample[index];
        });

        return Math.sqrt(sampleSum / normalSamples.length);
    }
}