import { getBulkInfo } from "./login.js"; class Voice { audioCtx: AudioContext; info: { wave: string | Function; freq: number }; playing: boolean; myArrayBuffer: AudioBuffer; gainNode: GainNode; buffer: Float32Array; source: AudioBufferSourceNode; constructor(wave: string | Function, freq: number, volume = 1) { this.audioCtx = new window.AudioContext(); this.info = { wave, freq }; this.playing = false; this.myArrayBuffer = this.audioCtx.createBuffer( 1, this.audioCtx.sampleRate, this.audioCtx.sampleRate ); this.gainNode = this.audioCtx.createGain(); this.gainNode.gain.value = volume; this.gainNode.connect(this.audioCtx.destination); this.buffer = this.myArrayBuffer.getChannelData(0); this.source = this.audioCtx.createBufferSource(); this.source.buffer = this.myArrayBuffer; this.source.loop = true; this.source.start(); this.updateWave(); } get wave(): string | Function { return this.info.wave; } get freq(): number { return this.info.freq; } set wave(wave: string | Function) { this.info.wave = wave; this.updateWave(); } set freq(freq: number) { this.info.freq = freq; this.updateWave(); } updateWave(): void { const func = this.waveFunction(); for (let i = 0; i < this.buffer.length; i++) { this.buffer[i] = func(i / this.audioCtx.sampleRate, this.freq); } } waveFunction(): Function { if (typeof this.wave === "function") { return this.wave; } switch (this.wave) { case "sin": return (t: number, freq: number) => { return Math.sin(t * Math.PI * 2 * freq); }; case "triangle": return (t: number, freq: number) => { return Math.abs(((4 * t * freq) % 4) - 2) - 1; }; case "sawtooth": return (t: number, freq: number) => { return ((t * freq) % 1) * 2 - 1; }; case "square": return (t: number, freq: number) => { return (t * freq) % 2 < 1 ? 1 : -1; }; case "white": return (_t: number, _freq: number) => { return Math.random() * 2 - 1; }; case "noise": return (_t: number, _freq: number) => { return 0; }; } return new Function(); } play(): void { if (this.playing) { return; } this.source.connect(this.gainNode); this.playing = true; } stop(): void { if (this.playing) { this.source.disconnect(); this.playing = false; } } static noises(noise: string): void { switch (noise) { case "three": { const voicy = new Voice("sin", 800); voicy.play(); setTimeout((_) => { voicy.freq = 1000; }, 50); setTimeout((_) => { voicy.freq = 1300; }, 100); setTimeout((_) => { voicy.stop(); }, 150); break; } case "zip": { const voicy = new Voice((t: number, freq: number) => { return Math.sin((t + 2) ** Math.cos(t * 4) * Math.PI * 2 * freq); }, 700); voicy.play(); setTimeout((_) => { voicy.stop(); }, 150); break; } case "square": { const voicy = new Voice("square", 600, 0.4); voicy.play(); setTimeout((_) => { voicy.freq = 800; }, 50); setTimeout((_) => { voicy.freq = 1000; }, 100); setTimeout((_) => { voicy.stop(); }, 150); break; } case "beep": { const voicy = new Voice("sin", 800); voicy.play(); setTimeout((_) => { voicy.stop(); }, 50); setTimeout((_) => { voicy.play(); }, 100); setTimeout((_) => { voicy.stop(); }, 150); break; } } } static get sounds() { return ["three", "zip", "square", "beep"]; } static setNotificationSound(sound: string) { const userinfos = getBulkInfo(); userinfos.preferences.notisound = sound; localStorage.setItem("userinfos", JSON.stringify(userinfos)); } static getNotificationSound() { const userinfos = getBulkInfo(); return userinfos.preferences.notisound; } } export { Voice };