-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
50f7d05
commit dcda33f
Showing
11 changed files
with
361 additions
and
248 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
var _=Object.defineProperty;var I=(c,u,w)=>u in c?_(c,u,{enumerable:!0,configurable:!0,writable:!0,value:w}):c[u]=w;var T=(c,u,w)=>(I(c,typeof u!="symbol"?u+"":u,w),w);var L=["utf-8","utf-16","utf-16be"],E=(c,u)=>{c.unsent=!1,c.enqueue(u)},R,o=(R=class{static lineRaw(c,u=0){if(u?.constructor!=Number||u<0||u>=L.length)throw new TypeError("Invalid split mode");if(u)throw new Error("UTF-16LE/BE currently not implemented");if(!c||c?.constructor!=ReadableStream)throw new TypeError("Not a readable stream");let w=c.getReader(),e,a=!1,i=[],h=0,b=0,S=0;return new ReadableStream({pull:async $=>{for($.unsent=!0;$.unsent;){if(!e||h>=e.length){h>b&&(i.push(e.subarray(b)),b=0);let{value:k,done:p}=await w.read();e=k,a=p,h=0}if(e){let k=e[h],p=!1;switch(k){case 10:{S==13?b++:p=!0;break}case 13:{p=!0;break}}if(p){if(i.length){i.push(e.subarray(b,h));let t=0;for(let g=0;g<i.length;g++)t+=i[g].length;let m=new Uint8Array(t),y=0;for(let g=0;g<i.length;g++)m.set(i[g],y),y+=i[g].length;E($,m),i=[]}else E($,e.subarray(b,h));b=h+1}S=k}if(a){if(b!=h&&i.push(e.subarray(b,h)),i.length){let k=0;for(let m=0;m<i.length;m++)k+=i[m].length;let p=new Uint8Array(k),t=0;for(let m=0;m<i.length;m++)p.set(i[m],t),t+=i[m].length;E($,p)}$.unsent=!1,$.close()}h++}}},new ByteLengthQueuingStrategy({highWaterMark:256}))}static line(c,u=0,w){let e=this.lineRaw(c,u).getReader(),a=new TextDecoder(w||L[u]);return new ReadableStream({pull:async i=>{let{value:h,done:b}=await e.read();h&&i.enqueue(a.decode(h)),b&&i.close()}})}},T(R,"SPLIT_UTF_8",0),T(R,"SPLIT_UTF_16_LE",1),T(R,"SPLIT_UTF_16_BE",2),R),B=o;var s=new TextEncoder;var d=(c,u)=>{c.unsent=!1,c.enqueue(u)},A=function(c){let u=c.getReader(),w=0,e=0,a=0,i,h=0,b=0,S=!1,r=0,$="",k=0,p=0,t=0,m=0,y=!1,g=0,x=0;return new ReadableStream({pull:async n=>{for(n.unsent=!0;n.unsent;){if(!i||e>=i.length){let{value:f,done:U}=await u.read();if(i&&(w+=i.length),e=0,i=f,U){n.close();return}}let P=w+e,l=i[e];switch(r>4&&S&&P-h>=b&&(n.enqueue(s.encode(` | ||
`)),r=0,h=0,b=0,S=!1),r){case 0:{switch($+=String.fromCharCode(l),$){case"MThd":{d(n,s.encode(`:hd | ||
`)),r=1,k=3,p=4,a=e+1,$="",S=!1;break}case"MTrk":{x++,d(n,s.encode(`:tr#${x} | ||
`)),r=1,k=3,p=5,a=e+1,$="",S=!1;break}default:$.length>=4&&($=$.substring(1,4))}break}case 1:{let f=e-a;f||(t=0),t=t<<8,t|=l,f>=3&&(t<0&&(t+=4294967296),r=k,e--);break}case 2:{let f=e-a;f||(t=0),t=t<<7,t|=l&127,(l<128||f>=3)&&(f&&e++,r=k,y&&(a=e+1,y=!1),e--);break}case 3:{d(n,s.encode(` ln ${t} | ||
`)),r=p,a=e+1,h=a+w,b=t,S=!0;break}case 4:{let f=e-a;if(f&1||(t=0),t=t<<8,t|=l,f&1)switch(f>>1){case 0:{d(n,s.encode(` ft ${t} | ||
`));break}case 1:{d(n,s.encode(` tc ${t} | ||
`));break}case 2:{t<32768?d(n,s.encode(` dv ${t} | ||
`)):d(n,s.encode(` td ${t} | ||
`)),r=0,a=e+1,t=0;break}}break}case 5:{r=2,k=6,e--;break}case 6:{if(e-a)switch(t&&(d(n,s.encode(` dt ${t} | ||
`)),t=0),l){case 240:{r=15;break}case 247:{r=16;break}case 255:{r=7;break}default:r=l>>4,g=l&15,a=e+1}else t&&d(n,s.encode(` dt ${t} | ||
`)),t=0;break}case 7:{d(n,s.encode(` mt ${l}`)),r=2,k=17,y=!0,a=e+1;break}case 15:{d(n,s.encode(" se")),r=2,k=17,e--,y=!0,a=e+1;break}case 16:{d(n,s.encode(" sc")),r=2,k=17,e--,y=!0,a=e+1;break}case 17:{let f=e-a;f==0&&(m=t,d(n,s.encode(` (${m})`))),f<0||(f<m?d(n,s.encode(` ${l.toString(16).padStart(2,"0")}`)):(d(n,s.encode(` | ||
`)),e--,r=5,a=e+1));break}case 8:{e-a?(d(n,s.encode(` ${l} | ||
`)),r=5,a=e+1):d(n,s.encode(` of ${`${g}`.padStart(2,"0")} ${l}`));break}case 9:{e-a?(d(n,s.encode(` ${l} | ||
`)),r=5,a=e+1):d(n,s.encode(` on ${`${g}`.padStart(2,"0")} ${l}`));break}case 10:{e-a?(d(n,s.encode(` ${l} | ||
`)),r=5,a=e+1):d(n,s.encode(` pa ${`${g}`.padStart(2,"0")} ${l}`));break}case 11:{e-a?(d(n,s.encode(` ${l} | ||
`)),r=5,a=e+1):d(n,s.encode(` cc ${`${g}`.padStart(2,"0")} ${l}`));break}case 12:{d(n,s.encode(` pc ${`${g}`.padStart(2,"0")} ${l} | ||
`)),r=5,a=e+1;break}case 13:{d(n,s.encode(` ca ${`${g}`.padStart(2,"0")} ${l} | ||
`)),r=5,a=e+1;break}case 14:{let f=e-a;f||(t=0),t|=l<<(f<<3),f&&(d(n,s.encode(` pb ${`${g}`.padStart(2,"0")} ${t-8192} | ||
`)),r=5,a=e+1);break}default:n.close()}e++}}},new ByteLengthQueuingStrategy({highWaterMark:256}))},C=function(c){let u=B.line(c).getReader(),w=0,e,a=!1;return new ReadableStream({pull:async i=>{let{value:h,done:b}=await u.read();b?i.close():w++}})};export{C as streamAssemble,A as streamDisassemble}; |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,144 +1,21 @@ | ||
// Middleware! | ||
"use strict"; | ||
|
||
import {CustomEventSource} from "../../libs/lightfelt@ltgcgo/ext/customEvents.js"; | ||
import {allocated} from "../state/index.mjs"; | ||
import MidiParser from "../../libs/midi-parser@colxi/main.min.js"; | ||
import {rawToPool} from "../basic/transform.js"; | ||
import {customInterpreter} from "../state/utils.js"; | ||
|
||
MidiParser.customInterpreter = customInterpreter; | ||
|
||
// Use track 240 to 255 for middleware. | ||
let toJson = function (data, track = 0) { | ||
let type = data[0] >> 4, part = data[0] & 15; | ||
let replyObj = { | ||
track: (track & 15) + 240, | ||
type, | ||
data: data.slice(1) | ||
}; | ||
if (type < 15) { | ||
replyObj.part = part; | ||
return replyObj; | ||
} if (type == 12) { | ||
replyObj.data = data[1]; | ||
} else { | ||
if (part == 0) { | ||
// SysEx | ||
return replyObj; | ||
} else { | ||
console.warn(`Unknown special event channel ${part}.`) | ||
}; | ||
}; | ||
}; | ||
let fromJson = function (json) { | ||
let type = json.type, part = json.part; | ||
if (type == 255) { | ||
// Directly reject sending meta events | ||
return; | ||
}; | ||
let binLength = 3; | ||
if (type == 12) { | ||
binLength = 2; | ||
} else if (type == 15) { | ||
binLength = json.data.length + 1; | ||
}; | ||
let newInstr = new Uint8Array(binLength); | ||
if (type != 15) { | ||
newInstr[0] = json.type * 16 + json.part; | ||
} else { | ||
newInstr[0] = 240; | ||
}; | ||
if (type == 12) { | ||
newInstr[1] = json.data; | ||
} else { | ||
if (json.data.forEach) { | ||
json.data.forEach((e, i) => { | ||
newInstr[i + 1] = e; | ||
}); | ||
} else { | ||
console.debug(`Type ${type} value ${json.data.constructor.name} cannot be iterated.`); | ||
}; | ||
}; | ||
return newInstr; | ||
}; | ||
|
||
let getBridge = function () { | ||
return new BroadcastChannel("cc.ltgc.octavia:MainInput"); | ||
}; | ||
let getBridgeOut = function () { | ||
return new BroadcastChannel("cc.ltgc.octavia:MainOutput"); | ||
}; | ||
|
||
let SimpleMidiEventEmitter = class extends CustomEventSource { | ||
#pool; | ||
#paused = true; | ||
#currentTime = 0; | ||
#lastEventTs = 0; | ||
#threadId = -1; | ||
get currentTime() { | ||
return this.#currentTime / 1000; | ||
}; | ||
get duration() { | ||
if (!this.#pool) { | ||
return 0; | ||
} else { | ||
return this.#pool[this.#pool.length - 1].end + 4; | ||
}; | ||
}; | ||
async load(blob) { | ||
if (blob) { | ||
this.#pool = rawToPool(MidiParser.parse(new Uint8Array(await blob.arrayBuffer()))); | ||
} else { | ||
this.pause(); | ||
this.#currentTime = 0; | ||
}; | ||
}; | ||
pause() { | ||
if (this.#threadId > -1) { | ||
clearInterval(this.#threadId); | ||
// All notes off | ||
for (let part = 0; part < 16; part ++) { | ||
this.dispatchEvent("midi", { | ||
delay: 0, | ||
data: {part, "type": 11, "data": [123, 0]} | ||
}); | ||
}; | ||
this.dispatchEvent("pause"); | ||
this.#threadId = -1; | ||
}; | ||
}; | ||
async play() { | ||
if (this.#threadId < 0) { | ||
this.#lastEventTs = Date.now(); | ||
this.#threadId = setInterval(() => { | ||
let timeNow = Date.now(), | ||
timeLast = this.#currentTime, | ||
timeDiff = timeNow - this.#lastEventTs; | ||
this.#currentTime += timeDiff; | ||
let events = this.#pool.step(this.currentTime); | ||
events?.forEach((e) => { | ||
this.dispatchEvent("midi", { | ||
delay: Math.round(e.start * 1000 - timeLast), | ||
data: e.data | ||
}); | ||
}); | ||
this.#lastEventTs = timeNow; | ||
}, 12.5); | ||
this.dispatchEvent("play"); | ||
}; | ||
}; | ||
constructor(pool) { | ||
super(); | ||
if (pool) { | ||
this.load(pool); | ||
}; | ||
}; | ||
}; | ||
|
||
export { | ||
toJson, | ||
fromJson, | ||
getBridge, | ||
getBridgeOut, | ||
SimpleMidiEventEmitter | ||
getBridgeOut | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Middleware! | ||
"use strict"; | ||
|
||
import {allocated} from "../state/index.mjs"; | ||
import MidiParser from "../../libs/midi-parser@colxi/main.min.js"; | ||
import {rawToPool} from "../basic/transform.js"; | ||
import {customInterpreter} from "../state/utils.js"; | ||
|
||
MidiParser.customInterpreter = customInterpreter; | ||
|
||
// Use track 240 to 255 for middleware. | ||
let toJson = function (data, track = 0) { | ||
let type = data[0] >> 4, part = data[0] & 15; | ||
let replyObj = { | ||
track: (track & 15) + 240, | ||
type, | ||
data: data.slice(1) | ||
}; | ||
if (type < 15) { | ||
replyObj.part = part; | ||
return replyObj; | ||
} if (type == 12) { | ||
replyObj.data = data[1]; | ||
} else { | ||
if (part == 0) { | ||
// SysEx | ||
return replyObj; | ||
} else { | ||
console.warn(`Unknown special event channel ${part}.`) | ||
}; | ||
}; | ||
}; | ||
let fromJson = function (json) { | ||
let type = json.type, part = json.part; | ||
if (type == 255) { | ||
// Directly reject sending meta events | ||
return; | ||
}; | ||
let binLength = 3; | ||
if (type == 12) { | ||
binLength = 2; | ||
} else if (type == 15) { | ||
binLength = json.data.length + 1; | ||
}; | ||
let newInstr = new Uint8Array(binLength); | ||
if (type != 15) { | ||
newInstr[0] = json.type * 16 + json.part; | ||
} else { | ||
newInstr[0] = 240; | ||
}; | ||
if (type == 12) { | ||
newInstr[1] = json.data; | ||
} else { | ||
if (json.data.forEach) { | ||
json.data.forEach((e, i) => { | ||
newInstr[i + 1] = e; | ||
}); | ||
} else { | ||
console.debug(`Type ${type} value ${json.data.constructor.name} cannot be iterated.`); | ||
}; | ||
}; | ||
return newInstr; | ||
}; | ||
|
||
let getBridge = function () { | ||
return new BroadcastChannel("cc.ltgc.octavia:MainInput"); | ||
}; | ||
let getBridgeOut = function () { | ||
return new BroadcastChannel("cc.ltgc.octavia:MainOutput"); | ||
}; | ||
|
||
export { | ||
toJson, | ||
fromJson, | ||
getBridge, | ||
getBridgeOut | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters