mirror of
https://github.com/exoticorn/microw8.git
synced 2026-11-13 23:17:19 +01:00
add pulse width support to other wave types
This commit is contained in:
1 parent
b626d2609a
commit
29186c806f
5 files changed
+78
-8
No files matched your search
@@ -37,7 +37,7 @@ export fn upd() {
|
|||||||
data 80 {
|
data 80 {
|
||||||
i8(
|
i8(
|
||||||
0, 64, 0, 128, 0, 0x90,
|
0, 64, 0, 128, 0, 0x90,
|
||||||
0, 128, 0, 128, 0, 0x4c,
|
0, 64, 0, 128, 0, 0x4c,
|
||||||
5, 128, 0, 128, 0, 0x4c,
|
5, 128, 0, 128, 0, 0x4c,
|
||||||
5, 128, 0, 128, 0, 0x4c,
|
5, 128, 0, 128, 0, 0x4c,
|
||||||
0xf8, 0x85,
|
0xf8, 0x85,
|
||||||
|
|||||||
Binary file not shown.
+17
-6
@@ -67,7 +67,10 @@ export fn gesSnd(t: i32) -> f32 {
|
|||||||
if wave < 2 {
|
if wave < 2 {
|
||||||
if wave {
|
if wave {
|
||||||
loop sawLoop {
|
loop sawLoop {
|
||||||
i!(GesBufferOffset + 128*4) = (phase & 65535) - 32768;
|
let p = (phase ^ 32768) << 16;
|
||||||
|
p = ((p ^ (p >> 31)) >> 15) + phaseShift;
|
||||||
|
p = (p < 0 | p > 65535) * 65535;
|
||||||
|
i!(GesBufferOffset + 128*4) = (phase ^ p & 65535) - 32768;
|
||||||
phase = phase + phaseInc;
|
phase = phase + phaseInc;
|
||||||
branch_if (i := i + 4) < 64*4: sawLoop;
|
branch_if (i := i + 4) < 64*4: sawLoop;
|
||||||
}
|
}
|
||||||
@@ -83,9 +86,12 @@ export fn gesSnd(t: i32) -> f32 {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if wave == 2 {
|
if wave == 2 {
|
||||||
|
let scale = pulseWidth + 256;
|
||||||
loop triLoop {
|
loop triLoop {
|
||||||
let s = phase << 16;
|
let s = phase << 16;
|
||||||
s = s ^ (s >> 31);
|
s = (s ^ (s >> 31));
|
||||||
|
s = (s >> 8) * scale;
|
||||||
|
s = (s ^ (s >> 31));
|
||||||
i!(GesBufferOffset + 128*4) = (s >> 15) - 32768;
|
i!(GesBufferOffset + 128*4) = (s >> 15) - 32768;
|
||||||
phase = phase + phaseInc;
|
phase = phase + phaseInc;
|
||||||
branch_if (i := i + 4) < 64*4: triLoop;
|
branch_if (i := i + 4) < 64*4: triLoop;
|
||||||
@@ -93,9 +99,10 @@ export fn gesSnd(t: i32) -> f32 {
|
|||||||
} else {
|
} else {
|
||||||
loop noiseLoop {
|
loop noiseLoop {
|
||||||
let s = (phase >> 12) & 4095;
|
let s = (phase >> 12) & 4095;
|
||||||
|
let pulse = ((phase >> 8) & 255) >= pulseWidth;
|
||||||
s = s * 0x6746ba73;
|
s = s * 0x6746ba73;
|
||||||
s = s ^ (s >> 15);
|
s = s ^ (s >> 15) * pulse;
|
||||||
i!(GesBufferOffset + 128*4) = (s * 0x83567a92) >> 16;
|
i!(GesBufferOffset + 128*4) = (s * 0x83567a92 + (phase << 16)) >> 16;
|
||||||
phase = phase + phaseInc;
|
phase = phase + phaseInc;
|
||||||
branch_if (i := i + 4) < 64*4: noiseLoop;
|
branch_if (i := i + 4) < 64*4: noiseLoop;
|
||||||
}
|
}
|
||||||
@@ -124,8 +131,12 @@ export fn gesSnd(t: i32) -> f32 {
|
|||||||
let ctrl = filter?0x6a;
|
let ctrl = filter?0x6a;
|
||||||
let note = i32.load16_u(filter * 2, 0x6c);
|
let note = i32.load16_u(filter * 2, 0x6c);
|
||||||
let inline freq = 440 as f32 * pow(2.0, (note - 69*256) as f32 / (12*256) as f32);
|
let inline freq = 440 as f32 * pow(2.0, (note - 69*256) as f32 / (12*256) as f32);
|
||||||
let F = min(4096 as f32, 8192 as f32 * sin(freq * (3.1415 / 44100.0))) as i32;
|
let F = (8192 as f32 * sin(min(0.25, freq / 44100 as f32) * 3.1415)) as i32;
|
||||||
let Q = 7350 - ctrl * (6530/255);
|
let Q = 8192 - (ctrl >> 4) * (7000/15);
|
||||||
|
let Qlimit = (8192*4096/F - F/2) * 3 / 4;
|
||||||
|
if Q > Qlimit {
|
||||||
|
Q = Qlimit;
|
||||||
|
}
|
||||||
let low_out = ctrl & 1;
|
let low_out = ctrl & 1;
|
||||||
let high_out = (ctrl >> 1) & 1;
|
let high_out = (ctrl >> 1) & 1;
|
||||||
let band_out = (ctrl >> 2) & 1;
|
let band_out = (ctrl >> 2) & 1;
|
||||||
|
|||||||
+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 s,o,r,i,l=B.getContext("2d"),F=l.createImageData(320,240),g=n.devkitMode,d=0,c=null==n.keyboardElement?B:n.keyboardElement;if(c){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&&D(o,!0);break;case"F9":A&&B.toBlob((e=>{u(e,".png")})),e.preventDefault();break;case"F10":A&&function(){if(r)return r.stop(),void(r=null);r=new MediaRecorder(B.captureStream(),{mimeType:"video/webm",videoBitsPerSecond:25e6});let e=[];r.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)}}r.onstop=()=>{t&&(t.hidden=!0),u(new Blob(e,{type:"video/webm"}),".webm")},r.start(),i=Date.now(),setTimeout(A,1e3)}(),e.preventDefault()}A?d|=t:d&=~t};c.onkeydown=e,c.onkeyup=e}async function D(r,i){s&&(s(),s=null);let c=new AudioContext({sampleRate:44100}),u=!0;s=()=>{c.close(),u=!1};let Q=r.byteLength;if(n.setMessage(Q),0==Q)return;await c.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%7C%7Cn.exports.gesSnd%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 f,E=new t(c),C=0,I=new Promise((e=>f=e)),p=e=>{C|=e,3==C&&f&&(f(!0),f=null)};E.port.onmessage=e=>p(e.data);let y=()=>{"suspended"==c.state?(n.startButton&&(n.startButton.style="",B.style="display:none"),(n.startButton||B).onclick=()=>{c.resume()}):(n.startButton&&(n.startButton.style="display:none",B.style=""),p(1))};c.onstatechange=y,y(),o=r;let w=window.location.pathname;if(Q<=1024&&!i){let e="";for(let t of A(r))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};g||(t.maximum=4);let B,s=new WebAssembly.Memory(t),i=A(s.buffer),f={env:{memory:s}},C=e=>{if(B&&(!g||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},p=async e=>(await WebAssembly.instantiate(e,f)).instance,y=async e=>C(await(await fetch(e)).arrayBuffer());B=await p(await y(e("data:application/wasm;base64,AGFzbQEAAAABFQRgAX8Bf2ACf38Bf2ADf39%2FAGAAAAIPAQNlbnYGbWVtb3J5AgAEAwkIAAABAgEAAAMGEAN%2FAUEAC38BQQALfwFBAAsHGQIIbG9hZF91dzgAAAp1bmNvbXByZXNzAAQIAQcKngUIxwEBB39BAC0AAEEBayIBQQBIBEAgAA8LQYDAByAAaiECIAFBAXEEQEEBQYHABxAEIQIFQYDAB0EAIAAQAwtBAEGAhA9BCBADQYiEDyEDQQghBEGBwAchBQNAIAUgAkLine 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,s={}){s.setMessage||(s.setMessage=(e,t)=>{t&&console.log("error: "+t)});let o,n,r,i,l=B.getContext("2d"),F=l.createImageData(320,240),d=s.devkitMode,c=0,C=null==s.keyboardElement?B:s.keyboardElement;if(C){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&&g(n,!0);break;case"F9":A&&B.toBlob((e=>{f(e,".png")})),e.preventDefault();break;case"F10":A&&function(){if(r)return r.stop(),void(r=null);r=new MediaRecorder(B.captureStream(),{mimeType:"video/webm",videoBitsPerSecond:25e6});let e=[];r.ondataavailable=t=>{e.push(t.data)};let t=s.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)}}r.onstop=()=>{t&&(t.hidden=!0),f(new Blob(e,{type:"video/webm"}),".webm")},r.start(),i=Date.now(),setTimeout(A,1e3)}(),e.preventDefault()}A?c|=t:c&=~t};C.onkeydown=e,C.onkeyup=e}async function g(r,i){o&&(o(),o=null);let C=new AudioContext({sampleRate:44100}),f=!0;o=()=>{C.close(),f=!1};let I=r.byteLength;if(s.setMessage(I),0==I)return;await C.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%7C%7Cn.exports.gesSnd%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,E=new t(C),D=0,m=new Promise((e=>Q=e)),u=e=>{D|=e,3==D&&Q&&(Q(!0),Q=null)};E.port.onmessage=e=>u(e.data);let w=()=>{"suspended"==C.state?(s.startButton&&(s.startButton.style="",B.style="display:none"),(s.startButton||B).onclick=()=>{C.resume()}):(s.startButton&&(s.startButton.style="display:none",B.style=""),u(1))};C.onstatechange=w,w(),n=r;let y=window.location.pathname;if(I<=1024&&!i){let e="";for(let t of A(r))e+=String.fromCharCode(t);y+="#"+btoa(e),y!=window.location.pathname+window.location.hash&&history.pushState(null,null,y)}B.width=B.width;try{let t={initial:4};d||(t.maximum=4);let B,o=new WebAssembly.Memory(t),i=A(o.buffer),Q={env:{memory:o}},D=e=>{if(B&&(!d||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,Q)).instance,w=async e=>D(await(await fetch(e)).arrayBuffer());B=await u(await w(e("data:application/wasm;base64,AGFzbQEAAAABFQRgAX8Bf2ACf38Bf2ADf39%2FAGAAAAIPAQNlbnYGbWVtb3J5AgAEAwkIAAABAgEAAAMGEAN%2FAUEAC38BQQALfwFBAAsHGQIIbG9hZF91dzgAAAp1bmNvbXByZXNzAAQIAQcKngUIxwEBB39BAC0AAEEBayIBQQBIBEAgAA8LQYDAByAAaiECIAFBAXEEQEEBQYHABxAEIQIFQYDAB0EAIAAQAwtBAEGAhA9BCBADQYiEDyEDQQghBEGBwAchBQNAIAUgAkLine truncated
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
include "../examples/include/microw8-api.cwa"
|
||||||
|
|
||||||
|
export fn upd() {
|
||||||
|
80?0 = (32!32 >> 11 << 6) | 5;
|
||||||
|
80?1 = (sin(time() * 6 as f32) * 95 as f32) as i32 + 128;
|
||||||
|
plotGes();
|
||||||
|
}
|
||||||
|
|
||||||
|
data 80 { i8 (
|
||||||
|
1, 128, 0, 69, 0, 15,
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0xff, 0xff,
|
||||||
|
0xc1, 0, 0, 110, 0, 0
|
||||||
|
) }
|
||||||
|
|
||||||
|
//import "env.gesSnd" fn gesSnd(i32) -> f32;
|
||||||
|
|
||||||
|
include "../platform/src/ges.cwa"
|
||||||
|
|
||||||
|
export fn snd(t: i32) -> f32 {
|
||||||
|
gesSnd(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
global mut samplePos: i32 = 0;
|
||||||
|
|
||||||
|
const SoundBuffer = 0x30000;
|
||||||
|
|
||||||
|
fn plotGes() {
|
||||||
|
rectangle(0 as f32, 10 as f32, 320 as f32, 320 as f32, 0);
|
||||||
|
let count = (time() * 44100 as f32) as i32 * 2 - samplePos;
|
||||||
|
let i: i32;
|
||||||
|
loop genLoop {
|
||||||
|
(i*4)$SoundBuffer = gesSnd(samplePos + i);
|
||||||
|
branch_if (i := i + 1) < count: genLoop;
|
||||||
|
}
|
||||||
|
samplePos = samplePos + count;
|
||||||
|
|
||||||
|
let ch: i32;
|
||||||
|
loop channelLoop {
|
||||||
|
let offset = 159;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
loop searchLoop {
|
||||||
|
offset = offset + 1;
|
||||||
|
branch_if (offset * 8 + ch - 8)$SoundBuffer < 0 as f32 | (offset * 8 + ch)$SoundBuffer >= 0 as f32 & offset + 160 < count: searchLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = ch + (offset - 160) * 8;
|
||||||
|
i = 0;
|
||||||
|
loop plotLoop {
|
||||||
|
setPixel(i, floor((i * 8 + offset)$SoundBuffer * 127 as f32) as i32 + 60 + ch * (120/8), 15);
|
||||||
|
branch_if (i := i + 1) < 320: plotLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
branch_if (ch := ch + 8) < 16: channelLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user