From 6788c54ad695e6b84a72a3e863bb5793a25417ab Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 30 Nov 2024 22:47:50 -0600 Subject: [PATCH] reorginization and new sound format --- gulpfile.cjs | 1 + src/webpage/audio/audio.md | 37 +++++ src/webpage/audio/audio.ts | 213 +++++--------------------- src/webpage/audio/index.html | 1 + src/webpage/audio/page.ts | 154 +++++++++++++++++++ src/webpage/audio/play.ts | 48 ++++++ src/webpage/audio/sounds.jasf | Bin 0 -> 263 bytes src/webpage/audio/track.ts | 46 ++++++ src/webpage/audio/voice.ts | 246 +++++++++++++++++++++++++++++++ src/webpage/channel.ts | 9 +- src/webpage/localuser.ts | 17 ++- src/webpage/utils/binaryUtils.ts | 9 ++ 12 files changed, 595 insertions(+), 186 deletions(-) create mode 100644 src/webpage/audio/audio.md create mode 100644 src/webpage/audio/play.ts create mode 100644 src/webpage/audio/sounds.jasf create mode 100644 src/webpage/audio/track.ts create mode 100644 src/webpage/audio/voice.ts diff --git a/gulpfile.cjs b/gulpfile.cjs index f317e6f..681c655 100644 --- a/gulpfile.cjs +++ b/gulpfile.cjs @@ -113,6 +113,7 @@ return gulp "src/**/*.webp", "src/**/*.gif", "src/**/*.svg", + "src/**/*.jasf", ],{encoding:false}) .pipe(plumber()) // Prevent pipe breaking caused by errors .pipe(gulp.dest("dist")); diff --git a/src/webpage/audio/audio.md b/src/webpage/audio/audio.md new file mode 100644 index 0000000..10ba3bd --- /dev/null +++ b/src/webpage/audio/audio.md @@ -0,0 +1,37 @@ +# Jank Audio format +This is a markdown file that will try to describe the jank client audio format in sufficient detail so people will know how this weird custom format works into the future. +This is a byte-aligned format, which uses the sequence jasf in asci as a magic number at the start. + +the next 8 bits will decide how many voices this file has/will provide, if the value is 255 you'll instead have a 16 bit number that follows for how many voices there are, this *should* be unused, but I wouldn't be totally surprised if it did get used. + +then it'll parse for that many voices, which will be formatted like the following: +name:String8; +length:f32; **if this is 0, this is not an custom sound and is instead refering to something else which will be explained laterâ„¢** + +Given a non-zero length, this will parse the sounds as following: +|instruction | description | +| ---------- | ----------- | +| 000 | read float32 and use as value | +| 001 | read time(it'll always be a value between 0 and 1) | +| 002 | read frequency in hz | +| 003 | the constant PI | +| 004 | Math.sin() on the following sequence | +| 005 | multiplies the next two expressions | +| 006 | adds the next two expressions | +| 007 | divides the first expression by the second | +| 008 | subtracts the second expression by the first | +| 009 | first expression to the power of the second | +| 010 | first expression to the modulo of the second | +| 011 | absolute power of the next expression | +| 012 | round the next expression | +| 013 | Math.cos() on the next expression | +> note +> this is likely to expand in the future as more things are needed, but this is just how it is right now. + +Once you've read all of the sounds in the file, you can move on to parsing the tracks. +This starts out by reading a u16 to find out how many tracks there are, then you'll go on to try and parse that many. + +each track will then read a u16 to find out how long it is, then it'll read bytes as the following. +it'll first read the index(which is either a u8 or u16 depending on if the amount of voices was u8 or u16), which is the index of the voice 1-indexed, then if it's not 0 it'll parse two float32s in this order, the volume then the pitch of the sound, if it was 0 it'll instead read one 32f as a delay in the track. if it's a default sound it'll also read a third 32f for length + +then finally you'll parse the audios which are the complete tracks. you'll first parse a u16 to get how many audios there are, then for each audio you'll first parse a string8 for the name, then a u16 for the length then according to the length you'll go on to parse a u16 to get the track (1-indexed again) where if it's 0 you'll instead add a delay according to the next f32, how many ever times according to the length. diff --git a/src/webpage/audio/audio.ts b/src/webpage/audio/audio.ts index cdc412f..d69a8c9 100644 --- a/src/webpage/audio/audio.ts +++ b/src/webpage/audio/audio.ts @@ -1,181 +1,34 @@ -class AVoice{ - 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; - }; - } - 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 AVoice("sin", 800); - voicy.play(); - setTimeout(_=>{ - voicy.freq = 1000; - }, 50); - setTimeout(_=>{ - voicy.freq = 1300; - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case"zip": { - const voicy = new AVoice((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 AVoice("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 AVoice("sin", 800); - voicy.play(); - setTimeout(_=>{ - voicy.stop(); - }, 50); - setTimeout(_=>{ - voicy.play(); - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case "join":{ - const voicy = new AVoice("triangle", 600,.1); - voicy.play(); - setTimeout(_=>{ - voicy.freq=800; - }, 75); - setTimeout(_=>{ - voicy.freq=1000; - }, 150); - setTimeout(_=>{ - voicy.stop(); - }, 200); - break; - } - case "leave":{ - const voicy = new AVoice("triangle", 850,.5); - voicy.play(); - setTimeout(_=>{ - voicy.freq=700; - }, 100); - setTimeout(_=>{ - voicy.stop(); - voicy.freq=400; - }, 180); - setTimeout(_=>{ - voicy.play(); - }, 200); - setTimeout(_=>{ - voicy.stop(); - }, 250); - break; - } - } - } - static get sounds(){ - return["three", "zip", "square", "beep"]; - } +import { BinRead } from "../utils/binaryUtils.js"; +import { Track } from "./track.js"; + +export class Audio{ + name:string; + tracks:(Track|number)[]; + constructor(name:string,tracks:(Track|number)[]){ + this.tracks=tracks; + this.name=name; + } + static parse(read:BinRead,trackarr:Track[]):Audio{ + const name=read.readString8(); + const length=read.read16(); + const tracks:(Track|number)[]=[] + for(let i=0;isetTimeout(res,thing)); + } + } + } } -export{ AVoice as AVoice }; diff --git a/src/webpage/audio/index.html b/src/webpage/audio/index.html index 75cb8e4..1d71d8f 100644 --- a/src/webpage/audio/index.html +++ b/src/webpage/audio/index.html @@ -19,6 +19,7 @@

I want to let the sound system of jank not be so hard coded, but I still need to work on everything a bit before that can happen. Thanks for your patience.

why does this tool need to exist?

For size reasons jank does not use normal sound files, so I need to make this whole format to be more adaptable

+ diff --git a/src/webpage/audio/page.ts b/src/webpage/audio/page.ts index a37af3f..ccc5d45 100644 --- a/src/webpage/audio/page.ts +++ b/src/webpage/audio/page.ts @@ -1,3 +1,157 @@ +import { BinWrite } from "../utils/binaryUtils.js"; import { setTheme } from "../utils/utils.js"; +import { Play } from "./play.js"; setTheme(); +const w=new BinWrite(2**12); +w.writeStringNo("jasf"); +w.write8(4); + +w.writeString8("sin"); +w.write32Float(0); +w.writeString8("triangle"); +w.write32Float(0); +w.writeString8("square"); +w.write32Float(0); + +w.writeString8("custom"); +w.write32Float(150); +//return Math.sin(((t + 2) ** Math.cos(t * 4)) * Math.PI * 2 * freq); +//Math.sin((((t+2)**Math.cos((t*4)))*((Math.PI*2)*f))) +w.write8(4);//sin +w.write8(5)//times +{ + w.write8(9);//Power + + { + w.write8(6);//adding + w.write8(1);//t + w.write8(0);w.write32Float(2);//2 + } + w.write8(13);//cos + w.write8(5);// times + w.write8(1);//t + w.write8(0);w.write32Float(4);//4 +} +{ + w.write8(5)//times + w.write8(5)//times + w.write8(3);//PI + w.write8(0);w.write32Float(2);//2 + w.write8(2);//freq +} + +w.write16(4);//3 tracks + +w.write16(1);//zip +w.write8(4); +w.write32Float(1) +w.write32Float(700) + +w.write16(3);//beep +{ + w.write8(1); + w.write32Float(1) + w.write32Float(700); + w.write32Float(50); + + w.write8(0); + w.write32Float(100); + + w.write8(1); + w.write32Float(1) + w.write32Float(700); + w.write32Float(50); +} + +w.write16(5);//three +{ + w.write8(1); + w.write32Float(1) + w.write32Float(800); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(1); + w.write32Float(1) + w.write32Float(1000); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(1); + w.write32Float(1) + w.write32Float(1300); + w.write32Float(50); +} + +w.write16(5);//square +{ + w.write8(3); + w.write32Float(1) + w.write32Float(600); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(3); + w.write32Float(1) + w.write32Float(800); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(3); + w.write32Float(1) + w.write32Float(1000); + w.write32Float(50); +} +w.write16(4);//2 audio + +w.writeString8("zip"); +w.write16(1); +w.write16(1); + +w.writeString8("beep"); +w.write16(1); +w.write16(2); + +w.writeString8("three"); +w.write16(1); +w.write16(3); + +w.writeString8("square"); +w.write16(1); +w.write16(4); +const buff=w.getBuffer(); +const play=Play.parseBin(buff); +/* +const zip=play.audios.get("square"); +if(zip){ + setInterval(()=>{ + zip.play() + },1000) + ; + console.log(play.voices[3][0].info.wave) +}; +*/ +console.log(play,buff); + +const download=document.getElementById("download"); +if(download){ + download.onclick=()=>{ + const blob = new Blob([buff], { type: "binary" }); + const downloadUrl = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = downloadUrl; + a.download = "sounds.jasf"; + document.body.appendChild(a); + a.click(); + URL.revokeObjectURL(downloadUrl); + } +} diff --git a/src/webpage/audio/play.ts b/src/webpage/audio/play.ts new file mode 100644 index 0000000..8ae81f9 --- /dev/null +++ b/src/webpage/audio/play.ts @@ -0,0 +1,48 @@ +import { BinRead } from "../utils/binaryUtils.js"; +import { Track } from "./track.js"; +import { AVoice } from "./voice.js"; +import { Audio } from "./audio.js"; +export class Play{ + voices:[AVoice,string][] + tracks:Track[] + audios:Map; + constructor(voices:[AVoice,string][],tracks:Track[],audios:Map){ + this.voices=voices; + this.tracks=tracks; + this.audios=audios; + } + static parseBin(buffer:ArrayBuffer){ + const read=new BinRead(buffer); + if(read.readStringNo(4)!=="jasf") throw new Error("this is not a jasf file"); + let voices=read.read8(); + let six=false; + if(voices===255){ + voices=read.read16(); + six=true; + } + const voiceArr:[AVoice,string][]=[]; + for(let i=0;i(); + for(let i=0;iz{tQ1 J^C2Sx3jnzKDJB2_ literal 0 HcmV?d00001 diff --git a/src/webpage/audio/track.ts b/src/webpage/audio/track.ts new file mode 100644 index 0000000..dac4af3 --- /dev/null +++ b/src/webpage/audio/track.ts @@ -0,0 +1,46 @@ +import { BinRead } from "../utils/binaryUtils.js"; +import { AVoice } from "./voice.js"; + +export class Track{ + seq:(AVoice|number)[]; + constructor(playing:(AVoice|number)[]){ + this.seq=playing; + } + static parse(read:BinRead,play:[AVoice,string][],six:boolean):Track{ + const length=read.read16(); + const play2:(AVoice|number)[]=[]; + for(let i=0;isetTimeout(res,thing)); + } + } + } +} diff --git a/src/webpage/audio/voice.ts b/src/webpage/audio/voice.ts new file mode 100644 index 0000000..703fa12 --- /dev/null +++ b/src/webpage/audio/voice.ts @@ -0,0 +1,246 @@ +import { BinRead } from "../utils/binaryUtils.js"; + +class AVoice{ + audioCtx: AudioContext; + info: { wave: string | Function; freq: number }; + playing: boolean; + myArrayBuffer: AudioBuffer; + gainNode: GainNode; + buffer: Float32Array; + source: AudioBufferSourceNode; + length=1; + constructor(wave: string | Function, freq: number, volume = 1,length=1000){ + this.length=length; + this.audioCtx = new window.AudioContext(); + this.info = { wave, freq }; + this.playing = false; + this.myArrayBuffer = this.audioCtx.createBuffer( + 1, + this.audioCtx.sampleRate*length/1000, + 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(); + } + clone(volume:number,freq:number,length=this.length){ + return new AVoice(this.wave,freq,volume,length); + } + 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; + }; + } + return new Function(); + } + play(): void{ + if(this.playing){ + return; + } + this.source.connect(this.gainNode); + this.playing = true; + } + playL(){ + this.play(); + setTimeout(()=>{ + this.stop(); + },this.length); + } + stop(): void{ + if(this.playing){ + this.source.disconnect(); + this.playing = false; + } + } + static noises(noise: string): void{ + switch(noise){ + case"three": { + const voicy = new AVoice("sin", 800); + voicy.play(); + setTimeout(_=>{ + voicy.freq = 1000; + }, 50); + setTimeout(_=>{ + voicy.freq = 1300; + }, 100); + setTimeout(_=>{ + voicy.stop(); + }, 150); + break; + } + case"zip": { + const voicy = new AVoice((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 AVoice("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 AVoice("sin", 800); + voicy.play(); + setTimeout(_=>{ + voicy.stop(); + }, 50); + setTimeout(_=>{ + voicy.play(); + }, 100); + setTimeout(_=>{ + voicy.stop(); + }, 150); + break; + } + case "join":{ + const voicy = new AVoice("triangle", 600,.1); + voicy.play(); + setTimeout(_=>{ + voicy.freq=800; + }, 75); + setTimeout(_=>{ + voicy.freq=1000; + }, 150); + setTimeout(_=>{ + voicy.stop(); + }, 200); + break; + } + case "leave":{ + const voicy = new AVoice("triangle", 850,.5); + voicy.play(); + setTimeout(_=>{ + voicy.freq=700; + }, 100); + setTimeout(_=>{ + voicy.stop(); + voicy.freq=400; + }, 180); + setTimeout(_=>{ + voicy.play(); + }, 200); + setTimeout(_=>{ + voicy.stop(); + }, 250); + break; + } + } + } + static get sounds(){ + return["three", "zip", "square", "beep"]; + } + static getVoice(read:BinRead):[AVoice,string]{ + const name = read.readString8(); + let length=read.readFloat32(); + let special:Function|string + if(length!==0){ + special=this.parseExpression(read); + }else{ + special=name; + length=1; + } + return [new AVoice(special,0,0,length),name] + } + static parseExpression(read:BinRead):Function{ + return new Function("t","f",`return ${this.PEHelper(read)};`); + } + static PEHelper(read:BinRead):string{ + let state=read.read8(); + switch(state){ + case 0: + return ""+read.readFloat32(); + case 1: + return "t"; + case 2: + return "f"; + case 3: + return `Math.PI` + case 4: + return `Math.sin(${this.PEHelper(read)})`; + case 5: + return `(${this.PEHelper(read)}*${this.PEHelper(read)})`; + case 6: + return `(${this.PEHelper(read)}+${this.PEHelper(read)})`; + case 7: + return `(${this.PEHelper(read)}/${this.PEHelper(read)})`; + case 8: + return `(${this.PEHelper(read)}-${this.PEHelper(read)})`; + case 9: + return `(${this.PEHelper(read)}**${this.PEHelper(read)})`; + case 10: + return `(${this.PEHelper(read)}%${this.PEHelper(read)})`; + case 11: + return `Math.abs(${this.PEHelper(read)})`; + case 12: + return `Math.round(${this.PEHelper(read)})`; + case 13: + return `Math.cos(${this.PEHelper(read)})`; + default: + throw new Error("unexpected case found!"); + + } + } +} + +export{ AVoice as AVoice }; diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 42717de..feba958 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -1,6 +1,6 @@ "use strict"; import{ Message }from"./message.js"; -import{ AVoice }from"./audio/audio.js"; +import{ AVoice }from"./audio/voice.js"; import{ Contextmenu }from"./contextmenu.js"; import{ Guild }from"./guild.js"; import{ Localuser }from"./localuser.js"; @@ -1403,7 +1403,12 @@ class Channel extends SnowFlake{ ); } notify(message: Message, deep = 0){ - AVoice.noises(this.localuser.getNotificationSound()); + if(this.localuser.play){ + const voice=this.localuser.play.audios.get(this.localuser.getNotificationSound()); + if(voice){ + voice.play(); + } + } if(!("Notification" in window)){ }else if(Notification.permission === "granted"){ let noticontent: string | undefined | null = message.content.textContent; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index b7b4087..8d6cf4c 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -1,7 +1,7 @@ import{ Guild }from"./guild.js"; import{ Channel }from"./channel.js"; import{ Direct }from"./direct.js"; -import{ AVoice }from"./audio/audio.js"; +import{ AVoice }from"./audio/voice.js"; import{ User }from"./user.js"; import{ getapiurls, SW }from"./utils/utils.js"; import { getBulkInfo, setTheme, Specialuser } from "./utils/utils.js"; @@ -14,6 +14,7 @@ import { Role } from "./role.js"; import { VoiceFactory } from "./voice.js"; import { I18n, langmap } from "./i18n.js"; import { Emoji } from "./emoji.js"; +import { Play } from "./audio/play.js"; const wsCodesRetry = new Set([4000,4001,4002, 4003, 4005, 4007, 4008, 4009]); @@ -40,6 +41,7 @@ class Localuser{ channelids: Map = new Map(); readonly userMap: Map = new Map(); voiceFactory?:VoiceFactory; + play?:Play; instancePing = { name: "Unknown", }; @@ -51,6 +53,9 @@ class Localuser{ this.userinfo.localuserStore = e; } constructor(userinfo: Specialuser | -1){ + Play.playURL("/audio/sounds.jasf").then((_)=>{ + this.play=_; + }) if(userinfo === -1){ return; } @@ -1234,8 +1239,7 @@ class Localuser{ } { const sounds = AVoice.sounds; - tas - .addSelect( + tas.addSelect( I18n.getTranslation("localuser.notisound"), _=>{ this.setNotificationSound(sounds[_]); @@ -1244,7 +1248,12 @@ class Localuser{ { defaultIndex: sounds.indexOf(this.getNotificationSound()) } ) .watchForChange(_=>{ - AVoice.noises(sounds[_]); + if(this.play){ + const voice=this.play.audios.get(sounds[_]) + if(voice){ + voice.play(); + } + } }); } diff --git a/src/webpage/utils/binaryUtils.ts b/src/webpage/utils/binaryUtils.ts index 322f192..f2c7c3c 100644 --- a/src/webpage/utils/binaryUtils.ts +++ b/src/webpage/utils/binaryUtils.ts @@ -20,6 +20,11 @@ class BinRead{ readString16(){ return this.readStringNo(this.read16()); } + readFloat32(){ + const float = this.view.getFloat32(this.i); + this.i += 4; + return float; + } readStringNo(length: number){ const array = new Uint8Array(length); for(let i = 0; i < length; i++){ @@ -38,6 +43,10 @@ class BinWrite{ this.buffer=new ArrayBuffer(maxSize); this.view=new DataView(this.buffer, 0); } + write32Float(numb:number){ + this.view.setFloat32(this.i,numb); + this.i+=4; + } write16(numb:number){ this.view.setUint16(this.i,numb); this.i+=2;