diff --git a/Makefile b/Makefile
index 9557609..23b6b3a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,9 @@
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/application.js : src/main.jsx src/application.jsx src/note_input.jsx src/radio_group.jsx
+ esbuild --bundle --jsx-factory=preact.h --jsx-fragment=preact.Fragment --format=esm \
+ src/main.jsx --outfile=js/application.js
js/preact.min.js : node_modules/preact/dist/preact.min.js
diff --git a/css/application.css b/css/application.css
index 6ce6f9c..c03ca51 100644
--- a/css/application.css
+++ b/css/application.css
@@ -14,4 +14,16 @@ html {
}
sub {
font-style: italic;
+}
+
+legend a {
+ cursor: pointer;
+ display: inline-block;
+ margin-left: .5em;
+}
+legend a:last-of-type {
+ margin-right: .5em;
+}
+legend a.selected {
+ color: blue;
}
\ No newline at end of file
diff --git a/src/application.jsx b/src/application.jsx
index d019218..b8b039d 100644
--- a/src/application.jsx
+++ b/src/application.jsx
@@ -1,11 +1,14 @@
// var h = preact.h;
+import { NoteInput, NoteFrequency } from './note_input';
+import { RadioGroup } from './radio_group';
function calc_sr(osc) {
// iigs is ~7.14Mhz / 8. Mirage is 8Mhz / 8
- return (28.63636*1000*1000/32) / (osc + 2);
+ // return (28.63636*1000*1000/32) / (osc + 2);
+ return (28_636_360/32) / (osc + 2);
}
function calc_shift(res,ws) {
@@ -18,12 +21,22 @@ function log2(x) {
}
+var _onames = [];
function Oscillators(props) {
- var options = []
- for (var i = 1; i < 33; ++i) {
- options.push();
+ if (!_onames.length) {
+ for (var i = 1; i < 33; ++i) {
+ var x = (calc_sr(i) / 1000 ).toFixed(2) + " kHz";
+ _onames.push(x)
+ }
}
+ var options = _onames.map( (x, ix) => {
+ var i = ix + 1;
+ return
+ });
+ // for (var i = 1; i < 33; ++i) {
+ // options.push();
+ // }
return ;
}
@@ -105,7 +118,53 @@ function SampleDisplay(props) {
return rv;
}
+function SineWave() {
+ var rv = [];
+ for (n = 0; n < 256; ++n) {
+ var x = 128 + Math.round(127 * Math.sin(n * Math.PI / 128));
+ var y = x.toString(16); if (y.length < 2) y = "0" + y;
+ rv.push( y );
+ if ((n & 0x07) == 0x07) rv.push("\n");
+ else rv.push(', ');
+ }
+
+ return (
+
+
+ {rv}
+
+
+ );
+}
+function NoteDisplay(props) {
+
+
+ var { osc, wave, note } = props;
+
+ const sr = calc_sr(osc);
+ const note_frq = NoteFrequency(note);
+
+ const f = note_frq / (sr / (1 << (8 + wave)));
+
+ var best_res = 0;
+ var best_freq = 0;
+ for (var res = 0; res < 8; ++res) {
+ var tmp = f * (1 << calc_shift(res, wave));
+ if (tmp >= 0x10000) break;
+ best_res = res;
+ best_freq = tmp;
+ }
+
+ return (
+ <>
+
Resolution: {best_res}
+ Frequency: {Math.round(best_freq)}
+
+ >
+
+ );
+}
// oscillators generate addresses, not samples.
// accumulator is 24-bit.
@@ -122,8 +181,10 @@ export class Application extends preact.Component {
this._waveChange = this.waveChange.bind(this);
this._resChange = this.resChange.bind(this);
this._freqChange = this.freqChange.bind(this);
+ this._noteChange = this.noteChange.bind(this);
+ this._tabChange = this.tabChange.bind(this);
- this.state = { osc: 32, wave: 0, res: 0, freq: 512 };
+ this.state = { osc: 32, wave: 0, res: 0, freq: 512, tab: 0, note: 4*12 };
}
oscChange(e) {
@@ -152,12 +213,22 @@ export class Application extends preact.Component {
this.setState( { freq: v } );
}
- form() {
+ tabChange(v) {
+ this.setState({ tab: v });
+ }
+
+ noteChange(v) {
+ this.setState({ note: v });
+ }
+
+ sampleChildren() {
var { osc, wave, res, freq } = this.state;
+ var shift = calc_shift(res, wave);
+
return (
-
+
+
+ >
);
}
- render() {
+ noteChildren() {
- var { osc, wave, res, freq } = this.state;
-
- var shift = calc_shift(res, wave);
+ var { osc, wave, note } = this.state;
return (
-
- { this.form() }
-
+ <>
- Scan Rate: { (calc_sr(osc) / 1000 ).toFixed(2) } kHz
+
+
+
+
+
+
+
-
-
+
+ >
+ );
+
+ }
+
+
+ render() {
+
+ var { osc, wave, res, freq, tab } = this.state;
+
+ // var shift = calc_shift(res, wave);
+
+ var children;
+ switch(tab){
+ case 0: children = this.sampleChildren(); break;
+ case 1: children = this.noteChildren(); break;
+ }
+
+
+ return (
+
+ { children }
+
);
}
}
-/*
-window.addEventListener('load', function(){
-
- preact.render(
- ,
- document.getElementById('application')
- );
-});
-*/
diff --git a/src/note_input.jsx b/src/note_input.jsx
new file mode 100644
index 0000000..2449fc3
--- /dev/null
+++ b/src/note_input.jsx
@@ -0,0 +1,90 @@
+
+
+const _notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
+
+const _base = [ 27.5, 55, 110, 220, 440, 880, ]
+
+function split_value(value) {
+ return [ value % 12, (value / 12) >> 0 ];
+}
+
+export function NoteName(value) {
+
+ var [note, octave] = split_value(value);
+
+ return _notes[note] + ' ' + octave;
+}
+
+export function NoteFrequency(value) {
+
+ var [note, octave] = split_value(value);
+
+ var n = (note + 3 ) % 12;
+ if (n >= 3) octave -= 1;
+ var base = 27.5 * (2 ** octave);
+
+ return base * 2 ** (n/12);
+}
+
+export class NoteInput extends preact.Component {
+
+ constructor(props) {
+ super(props);
+
+ this._noteChange = this.noteChange.bind(this);
+ this._octaveChange = this.octaveChange.bind(this);
+
+ }
+
+ noteChange(e) {
+ e.preventDefault();
+
+ var [note, octave] = split_value(this.props.value);
+ note = +e.target.value;
+ this.change(note, octave);
+ }
+
+ octaveChange(e) {
+ e.preventDefault();
+
+ var [note, octave] = split_value(this.props.value);
+ octave = +e.target.value;
+ this.change(note, octave);
+ }
+
+ change(note, octave) {
+ var {onChange} = this.props;
+ if (onChange) {
+ var value = note + (12 * octave);
+ onChange(value);
+ }
+ }
+
+ render() {
+
+ var { onChange, value } = this.props;
+
+ var notes = _notes.map( (x, ix) => {
+ return ;
+ });
+
+ var octaves = [];
+ for (var i = 0; i < 8; ++i) {
+ octaves.push(
+
+ );
+ }
+
+ var [note, octave] = split_value(value);
+
+ return (
+ <>
+
+ { ' ' }
+
+ { ' ' }
+ { NoteFrequency(value).toFixed(2) } Hz
+ >);
+ }
+
+}
diff --git a/src/radio_group.jsx b/src/radio_group.jsx
new file mode 100644
index 0000000..761acdc
--- /dev/null
+++ b/src/radio_group.jsx
@@ -0,0 +1,23 @@
+
+
+export function RadioGroup(props) {
+
+ var { options, value, onClick } = props;
+ var legend = [];
+ if (options) {
+
+ legend = options.map( (o, ix) => {
+ let _onClick = function(e) { e.preventDefault(); onClick(ix); }
+ return {o};
+ });
+
+ }
+
+ return (
+
+ );
+
+}