initial check in

This commit is contained in:
Kelvin Sherlock 2021-10-09 09:15:13 -04:00
commit 320054cc37
7 changed files with 286 additions and 0 deletions

22
Makefile Normal file
View File

@ -0,0 +1,22 @@
all: js/application.js js/preact.min.js | js
js/application.js : src/main.jsx src/application.jsx
esbuild --bundle --jsx-factory=preact.h --format=esm src/main.jsx --outfile=js/application.js
js/preact.min.js : node_modules/preact/dist/preact.min.js
cp node_modules/preact/dist/preact.min.js js/preact.min.js
js :
mkdir js
# js/application.js: src/application.jsx
# babel --react --transform-react-jsx pragma=h --loose --no-comments --runtime polyfill=false \
# --minify-constant-folding --minify-numeric-literals \
# -o $@ $<
.PHONY: clean
clean:
$(RM) js/application.js

17
css/application.css Normal file
View File

@ -0,0 +1,17 @@
html {
line-height: 4ex;
}
#form div {
line-height: 4ex;
}
#form label {
display: inline-block;
width: 6em;
}
#form label:after {
content: ": ";
}
sub {
font-style: italic;
}

19
index.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Ensoniq Buddy</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href='css/application.css' rel='stylesheet' type='text/css'>
</head>
<body>
<div id="application">
<!-- ReactJS Application Renders Here -->
</div>
<script src="js/preact.min.js"></script>
<script src="js/application.js"></script>
</body>
</html>

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"dependencies": {
"preact": "^10.5.14"
}
}

205
src/application.jsx Normal file
View File

@ -0,0 +1,205 @@
// var h = preact.h;
function calc_sr(osc) {
// iigs is ~7.14Mhz / 8. Mirage is 8Mhz / 8
return (28.63636*1000*1000/32) / (osc + 2);
}
function calc_shift(res,ws) {
return res + 9 - ws;
}
function log2(x) {
var y = Math.log2(x);
return (y >> 0) === y ? y : false;
}
function Oscillators(props) {
var options = []
for (var i = 1; i < 33; ++i) {
options.push(<option value={i} key={i}>{i}</option>);
}
return <select value={props.value} onChange={props.onChange}>{options}</select>;
}
function WaveSize(props) {
var options = []
for (var i = 8; i < 16; ++i) {
var ext = 1 << i;
var int = i - 8;
options.push(<option value={int} key={int}>{ext}</option>);
}
return <select value={props.value} onChange={props.onChange}>{options}</select>;
}
function Resolution(props) {
var options = []
for (var i = 0; i < 8; ++i) {
options.push(<option value={i} key={i}>{i}</option>);
}
return <select value={props.value} onChange={props.onChange}>{options}</select>;
}
function Frequency(props) {
/* number, min, max are not as strict as they ought to be */
return <input type="number" min="0" max="65535" value={props.value} onChange={props.onChange} />;
}
function nmultiply(x) {
if (x == 0) return 0;
if (x == 1) return <i>n</i>;
return <span>{x} * <i>n</i></span>;
// return paren ? <span>({x} * <i>n</i>)</span> : <span>{x} * <i>n</i></span>;
}
function SampleDisplay(props) {
var { shift, freq } = props;
var freq2 = log2(freq);
var fspan = <span title="Frequency">{freq}</span>;
var rv = [];
rv.push(
<div>
Sample<sub>n</sub> = RAM[ ({fspan} * <i>n</i>) >> {shift} ]
</div>
);
rv.push(
<div>
Sample<sub>n</sub> = RAM[ ({fspan} * <i>n</i>) / {1 << shift} ]
</div>
);
if (freq2) {
if (freq2 >= shift) {
rv.push(
<div>
Sample<sub>n</sub> = RAM[ { nmultiply(freq / ( 1 << shift)) } ]
</div>
);
} else {
rv.push(
<div>
Sample<sub>n</sub> = RAM[ { nmultiply(freq >> freq2) } >> {shift - freq2} ]
</div>
);
rv.push(
<div>
Sample<sub>n</sub> = RAM[ { nmultiply(freq >> freq2) } / { 1 << (shift - freq2) } ]
</div>
);
}
}
return rv;
}
// oscillators generate addresses, not samples.
// accumulator is 24-bit.
// frequency is 16-bit.
// accumulator n = freq * n
// sample n = memory[(freq * n) >> res. shift]
export class Application extends preact.Component {
constructor(props) {
super(props);
this._oscChange = this.oscChange.bind(this);
this._waveChange = this.waveChange.bind(this);
this._resChange = this.resChange.bind(this);
this._freqChange = this.freqChange.bind(this);
this.state = { osc: 32, wave: 0, res: 0, freq: 512 };
}
oscChange(e) {
e.preventDefault();
var v = +e.target.value || 0;
this.setState( { osc: v } );
}
waveChange(e) {
e.preventDefault();
var v = +e.target.value || 0;
this.setState( { wave: v } );
}
resChange(e) {
e.preventDefault();
var v = +e.target.value || 0;
this.setState( { res: v } );
}
freqChange(e) {
e.preventDefault();
var v = +e.target.value >> 0;
if (v < 0) v = 0;
if (v > 65535) v = 65535;
this.setState( { freq: v } );
}
form() {
var { osc, wave, res, freq } = this.state;
return (
<div id="form">
<div>
<label>Oscillators</label> <Oscillators value={osc} onChange={this._oscChange} />
</div>
<div>
<label>Wave Size</label> <WaveSize value={wave} onChange={this._waveChange} />
</div>
<div>
<label>Resolution</label> <Resolution value={res} onChange={this._resChange} />
</div>
<div>
<label>Frequency</label> <Frequency value={freq} onChange={this._freqChange} />
</div>
</div>
);
}
render() {
var { osc, wave, res, freq } = this.state;
var shift = calc_shift(res, wave);
return (
<div>
{ this.form() }
<div>
Scan Rate: { (calc_sr(osc) / 1000 ).toFixed(2) } kHz
</div>
<SampleDisplay freq={freq} shift={shift} />
</div>
);
}
}
/*
window.addEventListener('load', function(){
preact.render(
<Application />,
document.getElementById('application')
);
});
*/

10
src/main.jsx Normal file
View File

@ -0,0 +1,10 @@
import { Application } from './application';
window.addEventListener('load', function(){
preact.render(
<Application />,
document.getElementById('application')
);
});

8
yarn.lock Normal file
View File

@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
preact@^10.5.14:
version "10.5.14"
resolved "https://registry.yarnpkg.com/preact/-/preact-10.5.14.tgz#0b14a2eefba3c10a57116b90d1a65f5f00cd2701"
integrity sha512-KojoltCrshZ099ksUZ2OQKfbH66uquFoxHSbnwKbTJHeQNvx42EmC7wQVWNuDt6vC5s3nudRHFtKbpY4ijKlaQ==