jank-client-fork/src/webpage/audio.ts
2024-09-19 12:49:50 -05:00

164 lines
3.6 KiB
TypeScript

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 };