add Wave section with sine/square/triangle/sawtooth generator

This commit is contained in:
Kelvin Sherlock 2021-10-11 17:15:16 -04:00
parent f0ee46793d
commit 0cda8a7783
4 changed files with 139 additions and 31 deletions

View File

@ -2,7 +2,7 @@
all: js/application.js js/preact.min.js | js
js/application.js : src/main.jsx src/application.jsx src/note_input.jsx src/sine_wave_data.jsx
js/application.js : src/main.jsx src/application.jsx src/note_input.jsx src/wave_data.jsx
esbuild --bundle --jsx-factory=preact.h --jsx-fragment=preact.Fragment --format=esm \
src/main.jsx --outfile=js/application.js

View File

@ -3,7 +3,7 @@
import { NoteInput, NoteFrequency } from './note_input';
import { RadioGroup } from './radio_group';
import { SineWaveData } from './sine_wave_data';
import { WaveData } from './wave_data';
function calc_sr(osc) {
// iigs is ~7.14Mhz / 8. Mirage is 8Mhz / 8
@ -67,6 +67,26 @@ function Frequency(props) {
}
function Assembler(props) {
var options = ["Merlin", "ORCA/M"].map( (o, ix) => {
return <option key={ix} value={ix}>{o}</option>;
});
return <select {...props}>{options}</select>;
}
function WaveShape(props) {
var options = ["Sine", "Square", "Triangle", "Sawtooth"].map( (o, ix) => {
return <option key={ix} value={ix}>{o}</option>;
});
return <select {...props}>{options}</select>;
}
function nmultiply(x) {
if (x == 0) return 0;
if (x == 1) return <i>n</i>;
@ -148,7 +168,6 @@ function NoteDisplay(props) {
<div>Wave Size: 256</div>
<div>Resolution: {best_res}</div>
<div>Frequency: {Math.round(best_freq)}</div>
<SineWaveData />
</>
);
@ -172,8 +191,10 @@ export class Application extends preact.Component {
this._freqChange = this.freqChange.bind(this);
this._noteChange = this.noteChange.bind(this);
this._tabChange = this.tabChange.bind(this);
this._asmChange = this.asmChange.bind(this);
this._shapeChange = this.shapeChange.bind(this);
this.state = { osc: 32, wave: 0, res: 0, freq: 512, tab: 0, note: 4*12 };
this.state = { osc: 32, wave: 0, res: 0, freq: 512, tab: 0, note: 4*12, assembler: 0, shape: 0 };
}
oscChange(e) {
@ -212,6 +233,18 @@ export class Application extends preact.Component {
this.setState({ note: v });
}
asmChange(e) {
e.preventDefault();
var v = +e.target.value;
this.setState({ assembler: v});
}
shapeChange(e) {
e.preventDefault();
var v = +e.target.value;
this.setState({ shape: v});
}
sampleChildren() {
var { osc, wave, res, freq } = this.state;
@ -257,6 +290,24 @@ export class Application extends preact.Component {
}
waveChildren() {
var { assembler, shape } = this.state;
return (
<>
<div>
<label>Assembler</label> <Assembler value={assembler} onChange={this._asmChange} />
</div>
<div>
<label>Wave Type</label> <WaveShape value={shape} onChange={this._shapeChange} />
</div>
<WaveData assembler={assembler} shape={shape} />
</>
);
}
render() {
@ -268,9 +319,10 @@ export class Application extends preact.Component {
switch(tab){
case 0: children = this.sampleChildren(); break;
case 1: children = this.noteChildren(); break;
case 2: children = this.waveChildren(); break;
}
var options = ["Sample", "Note"].map( (o, ix) => {
var options = ["Sample", "Note", "Wave"].map( (o, ix) => {
return <option key={ix} value={ix}>{o}</option>;
});

View File

@ -1,26 +0,0 @@
export function SineWaveData() {
var data = [];
for (var n = 0; n < 256; ++n) {
var x = 128 + Math.round(127 * Math.sin(n * Math.PI / 128));
data.push( x || 1 );
}
var hex = data.map( (x) => x < 0x10 ? "0" + x.toString(16) : x.toString(16) );
var code = [];
for (var n = 0; n < 16; ++n) {
var line = "\t hex " + hex.slice(n * 16, n * 16 + 16).join("") + "\n"
code.push(line);
}
return (
<code>
<pre>
{code}
</pre>
</code>
);
}

82
src/wave_data.jsx Normal file
View File

@ -0,0 +1,82 @@
function sine() {
var rv = [];
for (var n = 0; n < 256; ++n) {
var x = 128 + Math.round(127 * Math.sin(n * Math.PI / 128));
rv.push( x || 1 );
}
return rv;
}
function square() {
var rv = [];
for (var n = 0; n < 128; ++n) rv.push(255);
for (var n = 0; n < 128; ++n) rv.push(1);
return rv;
}
function triangle() {
// 0x80 -> 0xff [25%] -> 0x80 [50%] -> 0x01 [75%] -> 0x80 [100%]
var rv = [];
for (var n = 0; n < 64; ++n) rv.push(0x80 + n * 2);
for (var n = 0; n < 128; ++n) rv.push(0xff - n * 2);
for (var n = 0; n < 64; ++n) rv.push(0x01 + n * 2);
return rv;
}
function sawtooth() {
var rv = [];
for (var n = 0; n < 128; ++n) rv.push(0x80 + n);
for (var n = 0; n < 128; ++n) rv.push(0x01 + n);
return rv;
}
export function WaveData(props) {
var {assembler, shape} = props;
var data;
switch(shape) {
case 0: data = sine(); break;
case 1: data = square(); break;
case 2: data = triangle(); break;
case 3: data = sawtooth(); break;
}
var hex = data.map( (x) => x < 0x10 ? "0" + x.toString(16) : x.toString(16) );
var code = [];
if (assembler == 0) {
// merlin
for (var n = 0; n < 16; ++n) {
var line = " hex " + hex.slice(n * 16, n * 16 + 16).join("") + "\n"
code.push(line);
}
}
if (assembler == 1) {
// orca/m
for (var n = 0; n < 16; ++n) {
var line = " dc h'" + hex.slice(n * 16, n * 16 + 16).join("") + "'\n"
code.push(line);
}
}
return (
<code>
<pre>
{code}
</pre>
</code>
);
}