mirror of
https://github.com/exoticorn/microw8.git
synced 2026-11-13 23:17:19 +01:00
sync sound registers to sound thread
This commit is contained in:
1 parent
2033f9a172
commit
780caf965a
4 files changed
+61
-5
No files matched your search
@@ -0,0 +1,45 @@
|
||||
include "../include/microw8-api.cwa"
|
||||
|
||||
export fn upd() {
|
||||
let T = 32!32 / 120;
|
||||
|
||||
let inline riff_pos = abs(((T&31) - 16) as f32) as i32;
|
||||
let lazy shift = ((1-((T>>5)&3))%2-1) * 2;
|
||||
|
||||
let inline note_count = 5 - (T >= 512);
|
||||
let inline octave = (riff_pos/5) * 12;
|
||||
let inline riff_note = 5514 >> (riff_pos % note_count * 4) & 15;
|
||||
let inline melody_note = shift + octave - riff_note;
|
||||
|
||||
80?1 = melody_note + 64;
|
||||
}
|
||||
|
||||
export fn snd(t: i32) -> f32 {
|
||||
gesSample(t)
|
||||
}
|
||||
|
||||
const gesStateOffset = 112;
|
||||
const gesBufferOffset = 120;
|
||||
|
||||
fn gesSample(t: i32) -> f32 {
|
||||
if !(t & 127) {
|
||||
let i: i32;
|
||||
loop clearLoop {
|
||||
i!gesBufferOffset = 0;
|
||||
branch_if (i := i + 4) < 128*4: clearLoop;
|
||||
}
|
||||
|
||||
let phase = 0!gesStateOffset;
|
||||
let inline note = 80?1;
|
||||
let inline freq = 440 as f32 * pow(2.0, (note - 69) as f32 / 12 as f32);
|
||||
let phaseInc = (freq * (65536.0 / 88200.0)) as i32;
|
||||
i = 0;
|
||||
loop osciLoop {
|
||||
i!gesBufferOffset = (phase & 65535) - 32768;
|
||||
phase = phase + phaseInc;
|
||||
branch_if (i := i + 4) < 128*4: osciLoop;
|
||||
}
|
||||
0!gesStateOffset = phase;
|
||||
}
|
||||
(((t & 127) * 4)!gesBufferOffset) as f32 / 32768 as f32
|
||||
}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<!doctype html><html><head><meta charset="utf8"><title>uw8-run</title><style>body,canvas,html{background-color:#202024;margin:0;padding:0}body,html{height:100%}body{display:grid;grid-template-rows:1fr}#screen{align-self:center;border:4px solid #303040;image-rendering:pixelated;justify-self:center}#message{background-color:rgba(0,0,0,.4);color:#c64;font:700 12pt sans-serif;padding:8px;position:absolute;width:calc(100% - 16px);z-index:2}@media (min-width:648px) and (min-height:488px){#screen{height:480px;width:640px}}@media (min-width:968px) and (min-height:728px){#screen{height:720px;width:960px}}</style></head><body> <canvas id="screen" width="320" height="240" tabindex="1"> </canvas> <div id="message"></div> </body><script type="module">function e(e){return e&&e.__esModule?e.default:e}class t extends AudioWorkletNode{constructor(e){super(e,"apu",{outputChannelCount:[2]})}}let A=e=>new Uint8Array(e),a=e=>new Uint32Array(e);let B=function(B,n={}){n.setMessage||(n.setMessage=(e,t)=>{t&&console.log("error: "+t)});let r,o,s,i,l=B.getContext("2d"),F=l.createImageData(320,240),c=n.devkitMode,g=0,d=null==n.keyboardElement?B:n.keyboardElement;if(d){let e=e=>{let t,A="keydown"==e.type;switch(e.code){case"ArrowUp":t=1;break;case"ArrowDown":t=2;break;case"ArrowLeft":t=4;break;case"ArrowRight":t=8;break;case"KeyZ":t=16;break;case"KeyX":t=32;break;case"KeyA":t=64;break;case"KeyS":t=128;break;case"KeyR":A&&f(o,!0);break;case"F9":A&&B.toBlob((e=>{D(e,".png")})),e.preventDefault();break;case"F10":A&&function(){if(s)return s.stop(),void(s=null);s=new MediaRecorder(B.captureStream(),{mimeType:"video/webm",videoBitsPerSecond:25e6});let e=[];s.ondataavailable=t=>{e.push(t.data)};let t=n.timerElement;t&&(t.hidden=!1,t.innerText="00:00");function A(){if(i){if(t){let e=Math.floor((Date.now()-i)/1e3);t.innerText=Math.floor(e/60).toString().padStart(2,"0")+":"+(e%60).toString().padStart(2,"0")}setTimeout(A,1e3)}}s.onstop=()=>{t&&(t.hidden=!0),D(new Blob(e,{type:"video/webm"}),".webm")},s.start(),i=Date.now(),setTimeout(A,1e3)}(),e.preventDefault()}A?g|=t:g&=~t};d.onkeydown=e,d.onkeyup=e}async function f(s,i){r&&(r(),r=null);let d=new AudioContext({sampleRate:44100}),D=!0;r=()=>{d.close(),D=!1},await d.audioWorklet.addModule(e("data:application/javascript,class%20e%20extends%20AudioWorkletProcessor%7Bconstructor%28%29%7Bsuper%28%29%2Cthis.sampleIndex%3D0%2Cthis.port.onmessage%3De%3D%3E%7Bthis.load%28e.data%5B0%5D%2Ce.data%5B1%5D%29%7D%7Dasync%20load%28e%2Cs%29%7Blet%20t%3D%7Benv%3A%7Bmemory%3Anew%20WebAssembly.Memory%28%7Binitial%3A4%2Cmaximum%3A4%7D%29%7D%7D%3Bfor%28let%20e%20of%5B%22acos%22%2C%22asin%22%2C%22atan%22%2C%22atan2%22%2C%22cos%22%2C%22exp%22%2C%22log%22%2C%22sin%22%2C%22tan%22%2C%22pow%22%5D%29t.env%5Be%5D%3DMath%5Be%5D%3Bfor%28let%20e%3D9%3Be%3C64%3B%2B%2Be%29t.env%5B%22reserved%22%2Be%5D%3D%28%29%3D%3E%7B%7D%3Bfor%28let%20e%3D0%3Be%3C16%3B%2B%2Be%29t.env%5B%22g_reserved%22%2Be%5D%3D0%3Blet%20a%3Dasync%20e%3D%3E%28await%20WebAssembly.instantiate%28e%2Ct%29%29.instance%2Cn%3Dawait%20a%28e%29%3Bfor%28let%20e%20in%20n.exports%29t.env%5Be%5D%3Dn.exports%5Be%5D%3Blet%20o%3Dawait%20a%28s%29%3Bthis.snd%3Do.exports.snd%7Dprocess%28e%2Cs%2Ct%29%7Bif%28this.snd%29%7Blet%20e%3Ds%5B0%5D%2Ct%3Dthis.sampleIndex%2Ca%3De%5B0%5D.length%3Bfor%28let%20s%3D0%3Bs%3Ca%3B%2B%2Bs%29e%5B0%5D%5Bs%5D%3Dthis.snd%28t%2B%2B%29%2Ce%5B1%5D%5Bs%5D%3Dthis.snd%28t%2B%2B%29%3Bthis.sampleIndex%3D4294967295%26t%7Dreturn%210%7D%7DregisterProcessor%28%22apu%22%2Ce%29%3B"));let Q=new t(d),C=s.byteLength;if(n.setMessage(C),0==C)return;o=s;let E=window.location.pathname;if(C<=1024&&!i){let e="";for(let t of A(s))e+=String.fromCharCode(t);E+="#"+btoa(e),E!=window.location.pathname+window.location.hash&&history.pushState(null,null,E)}B.width=B.width;try{let t={initial:4};c||(t.maximum=4);let B,r=new WebAssembly.Memory(t),i=A(r.buffer),E={env:{memory:r}},I=e=>{if(B&&(!c||0!=A(e)[0])){i.set(A(e));let t=B.exports.load_uw8(e.byteLength);e=new ArrayBuffer(t),A(e).set(i.slice(0,t))}return e},u=async e=>(await WebAssembly.instantiate(e,E)).instance,M=async e=>I(await(await fetch(e)).arrayBuffer());B=await u(await M(e("data:application/wasm;base64,AGFzbQEAAAABFQRgAX8Bf2ACf38Bf2ADf39%2FAGAAAAIPAQNlbnYGbWVtb3J5AgAEAwkIAAABAgEAAAMGEAN%2FAUEAC38BQQALfwFBAAsHGQIIbG9hZF91dzgAAAp1bmNvbXByZXNzAAQIAQcKngUIxwEBB39BAC0AAEEBayIBQQBIBEAgAA8LQYDAByAAaiECIAFBAXEEQEEBQYHABxAEIQIFQYDAB0EAIAAQAwtBAEGAhA9BCBADQYiEDyEDQQghBEGBwAchBQNAIAUgAkggAyMATiAFLQAAIAMtAABMcnEEQCAEIAQgBRACIgZqIQQgAyMASCAFLQAAIAMtAABGcQRAIAMgAxABaiEDCyAFIAZqIQUMAQsgAyMASARAIAQgBCADEAIiB2ohBCADIAdqIQMMAQsLIAQLPAEEfyAAIQEDQCACIAFBAWoiAS0AACIEQf8AcSADdHIhAiADQQdqIQMgBEEHdQ0ACyABQQFqIABrIAJqCxIBAX8gACABIAEQASICEAMgAgskAANAIAJBAEoEQCAAIAJBAWsiAmogASACai0AADoAAAwBCwsLqQEBBn8gACQBQQAkAgNAIANBgAE6AICADyADQQFqIgNBgQNIDQALAkADQEEAEAYiBQRAIAQEf0EBBUGAAhAGCwRAQYECEAVBAWsiAkUNAwtBwQIQBSEGA0AgASABIAJrLQAAOgAAIAFBAWohASAGQQFrIgYNAAsFQQEhBwNAIAdBAXQgBxAGciIHQYACSA0ACyABIAc6AAAgAUEBaiEBCyAFIQQMAAsLIAELNAECfwNAIAAgAmoQBgRAIAEgACACakEgaLine truncated
|
||||
<!doctype html><html><head><meta charset="utf8"><title>uw8-run</title><style>body,canvas,html{background-color:#202024;margin:0;padding:0}body,html{height:100%}body{display:grid;grid-template-rows:1fr}#screen{align-self:center;border:4px solid #303040;image-rendering:pixelated;justify-self:center}#message{background-color:rgba(0,0,0,.4);color:#c64;font:700 12pt sans-serif;padding:8px;position:absolute;width:calc(100% - 16px);z-index:2}@media (min-width:648px) and (min-height:488px){#screen{height:480px;width:640px}}@media (min-width:968px) and (min-height:728px){#screen{height:720px;width:960px}}</style></head><body> <canvas id="screen" width="320" height="240" tabindex="1"> </canvas> <div id="message"></div> </body><script type="module">function e(e){return e&&e.__esModule?e.default:e}class t extends AudioWorkletNode{constructor(e){super(e,"apu",{outputChannelCount:[2]})}}let A=(...e)=>new Uint8Array(...e),a=(...e)=>new Uint32Array(...e);let B=function(B,n={}){n.setMessage||(n.setMessage=(e,t)=>{t&&console.log("error: "+t)});let s,r,o,i,l=B.getContext("2d"),c=l.createImageData(320,240),F=n.devkitMode,g=0,d=null==n.keyboardElement?B:n.keyboardElement;if(d){let e=e=>{let t,A="keydown"==e.type;switch(e.code){case"ArrowUp":t=1;break;case"ArrowDown":t=2;break;case"ArrowLeft":t=4;break;case"ArrowRight":t=8;break;case"KeyZ":t=16;break;case"KeyX":t=32;break;case"KeyA":t=64;break;case"KeyS":t=128;break;case"KeyR":A&&f(r,!0);break;case"F9":A&&B.toBlob((e=>{D(e,".png")})),e.preventDefault();break;case"F10":A&&function(){if(o)return o.stop(),void(o=null);o=new MediaRecorder(B.captureStream(),{mimeType:"video/webm",videoBitsPerSecond:25e6});let e=[];o.ondataavailable=t=>{e.push(t.data)};let t=n.timerElement;t&&(t.hidden=!1,t.innerText="00:00");function A(){if(i){if(t){let e=Math.floor((Date.now()-i)/1e3);t.innerText=Math.floor(e/60).toString().padStart(2,"0")+":"+(e%60).toString().padStart(2,"0")}setTimeout(A,1e3)}}o.onstop=()=>{t&&(t.hidden=!0),D(new Blob(e,{type:"video/webm"}),".webm")},o.start(),i=Date.now(),setTimeout(A,1e3)}(),e.preventDefault()}A?g|=t:g&=~t};d.onkeydown=e,d.onkeyup=e}async function f(o,i){s&&(s(),s=null);let d=new AudioContext({sampleRate:44100}),D=!0;s=()=>{d.close(),D=!1};let C=o.byteLength;if(n.setMessage(C),0==C)return;await d.audioWorklet.addModule(e("data:application/javascript,let%20e%3D%28...e%29%3D%3Enew%20Uint8Array%28...e%29%3Bclass%20s%20extends%20AudioWorkletProcessor%7Bconstructor%28%29%7Bsuper%28%29%2Cthis.sampleIndex%3D0%2Cthis.port.onmessage%3Ds%3D%3E%7Bthis.memory%3Fe%28this.memory.buffer%2C80%2C32%29.set%28e%28s.data%29%29%3Athis.load%28s.data%5B0%5D%2Cs.data%5B1%5D%29%7D%7Dasync%20load%28e%2Cs%29%7Blet%20t%3Dnew%20WebAssembly.Memory%28%7Binitial%3A4%2Cmaximum%3A4%7D%29%2Ca%3D%7Benv%3A%7Bmemory%3At%7D%7D%3Bfor%28let%20e%20of%5B%22acos%22%2C%22asin%22%2C%22atan%22%2C%22atan2%22%2C%22cos%22%2C%22exp%22%2C%22log%22%2C%22sin%22%2C%22tan%22%2C%22pow%22%5D%29a.env%5Be%5D%3DMath%5Be%5D%3Bfor%28let%20e%3D9%3Be%3C64%3B%2B%2Be%29a.env%5B%22reserved%22%2Be%5D%3D%28%29%3D%3E%7B%7D%3Bfor%28let%20e%3D0%3Be%3C16%3B%2B%2Be%29a.env%5B%22g_reserved%22%2Be%5D%3D0%3Blet%20r%3Dasync%20e%3D%3E%28await%20WebAssembly.instantiate%28e%2Ca%29%29.instance%2Cn%3Dawait%20r%28e%29%3Bfor%28let%20e%20in%20n.exports%29a.env%5Be%5D%3Dn.exports%5Be%5D%3Blet%20o%3Dawait%20r%28s%29%3Bthis.memory%3Dt%2Cthis.snd%3Do.exports.snd%2Cthis.port.postMessage%282%29%7Dprocess%28e%2Cs%2Ct%29%7Bif%28this.snd%29%7Blet%20e%3Ds%5B0%5D%2Ct%3Dthis.sampleIndex%2Ca%3De%5B0%5D.length%3Bfor%28let%20s%3D0%3Bs%3Ca%3B%2B%2Bs%29e%5B0%5D%5Bs%5D%3Dthis.snd%28t%2B%2B%29%2Ce%5B1%5D%5Bs%5D%3Dthis.snd%28t%2B%2B%29%3Bthis.sampleIndex%3D4294967295%26t%7Dreturn%210%7D%7DregisterProcessor%28%22apu%22%2Cs%29%3B"));let Q,u=new t(d),E=0,I=new Promise((e=>Q=e)),m=e=>{E|=e,3==E&&Q&&(Q(!0),Q=null)};u.port.onmessage=e=>m(e.data);let p=()=>{"suspended"==d.state?(n.startButton&&(n.startButton.style="",B.style="display:none"),(n.startButton||B).onclick=()=>{d.resume()}):(n.startButton&&(n.startButton.style="display:none",B.style=""),m(1))};d.onstatechange=p,p(),r=o;let w=window.location.pathname;if(C<=1024&&!i){let e="";for(let t of A(o))e+=String.fromCharCode(t);w+="#"+btoa(e),w!=window.location.pathname+window.location.hash&&history.pushState(null,null,w)}B.width=B.width;try{let t={initial:4};F||(t.maximum=4);let B,s=new WebAssembly.Memory(t),i=A(s.buffer),Q={env:{memory:s}},E=e=>{if(B&&(!F||0!=A(e)[0])){i.set(A(e));let t=B.exports.load_uw8(e.byteLength);e=new ArrayBuffer(t),A(e).set(i.slice(0,t))}return e},m=async e=>(await WebAssembly.instantiate(e,Q)).instance,p=async e=>E(await(await fetch(e)).arrayBuffer());B=await m(await p(e("data:application/wasm;base64,AGFzbQEAAAABFQRgAX8Bf2ACf38Bf2ADf39%2FAGAAAAIPAQNlbnYGbWVtb3J5AgAEAwkIAAABAgEAAAMGEAN%2FAUEAC38BQQALfwFBAAsHGQIIbG9hZF91dzgAAAp1bmNvbXByZXNzAAQIAQcKngUIxwEBB39BAC0AAEEBayIBQQBIBEAgAA8LQYDAByAAaiECIAFBAXEEQEEBQYHABxAEIQIFQYDAB0EAIAAQAwtBAEGAhA9BCBADQYiEDyEDQQghBEGBwAchBQNAIAUgAkggAyMATiAFLQAAIAMtAABMLine truncated
|
||||
+8
-1
@@ -1,9 +1,14 @@
|
||||
let U8 = (...a) => new Uint8Array(...a);
|
||||
class APU extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
super();
|
||||
this.sampleIndex = 0;
|
||||
this.port.onmessage = (ev) => {
|
||||
this.load(ev.data[0], ev.data[1]);
|
||||
if(this.memory) {
|
||||
U8(this.memory.buffer, 80, 32).set(U8(ev.data));
|
||||
} else {
|
||||
this.load(ev.data[0], ev.data[1]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,6 +43,8 @@ class APU extends AudioWorkletProcessor {
|
||||
|
||||
let instance = await instantiate(data);
|
||||
|
||||
this.memory = memory;
|
||||
|
||||
this.snd = instance.exports.snd;
|
||||
|
||||
this.port.postMessage(2);
|
||||
|
||||
+7
-3
@@ -8,8 +8,8 @@ class AudioNode extends AudioWorkletNode {
|
||||
}
|
||||
}
|
||||
|
||||
let U8 = (d) => new Uint8Array(d);
|
||||
let U32 = (d) => new Uint32Array(d);
|
||||
let U8 = (...a) => new Uint8Array(...a);
|
||||
let U32 = (...a) => new Uint32Array(...a);
|
||||
|
||||
export default function MicroW8(screen, config = {}) {
|
||||
if(!config.setMessage) {
|
||||
@@ -272,8 +272,12 @@ export default function MicroW8(screen, config = {}) {
|
||||
instance.exports.upd();
|
||||
}
|
||||
platform_instance.exports.endFrame();
|
||||
|
||||
let soundRegisters = new ArrayBuffer(32);
|
||||
U8(soundRegisters).set(U8(memory.buffer, 80, 32));
|
||||
audioNode.port.postMessage(soundRegisters, [soundRegisters]);
|
||||
|
||||
let palette = U32(memory.buffer.slice(0x13000, 0x13000 + 1024));
|
||||
let palette = U32(memory.buffer, 0x13000, 1024);
|
||||
for (let i = 0; i < 320 * 240; ++i) {
|
||||
buffer[i] = palette[memU8[i + 120]] | 0xff000000;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user