improve prettier and ts config, format files
This commit is contained in:
parent
4907d1f38b
commit
840c35090f
16 changed files with 118 additions and 185 deletions
6
.prettierignore
Normal file
6
.prettierignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
pnpm-lock.yaml
|
||||
package.json5
|
||||
assets/
|
||||
*.css
|
||||
# https://github.com/prettier/prettier/issues/5019
|
||||
*.md
|
43
INFO.md
43
INFO.md
|
@ -9,14 +9,14 @@ for example lower values could move the speaker inward while higher values move
|
|||
|
||||
left to right on the settings bar is:
|
||||
|
||||
- time, click button to change unit (t is samples and matches t variable)
|
||||
- playback controls
|
||||
- oscillioscope zoom
|
||||
- oscillioscope draw mode
|
||||
- playback mode (read info section on webpage for explanations)
|
||||
- sample rate (samples per second, higher values give higher quality audio to an extent, higher than 48000 is unneccecary)
|
||||
- sample rate divisor (skips samples for performance, could affect playback quite a bit if static variables are used)
|
||||
- volume
|
||||
1. time, click button to change unit (t is samples and matches t variable)
|
||||
2. playback controls
|
||||
3. oscillioscope zoom
|
||||
4. oscillioscope draw mode
|
||||
5. playback mode (read info section on webpage for explanations)
|
||||
6. sample rate (samples per second, higher values give higher quality audio to an extent, higher than 48000 is unneccecary)
|
||||
7. sample rate divisor (skips samples for performance, could affect playback quite a bit if static variables are used)
|
||||
8. volume
|
||||
|
||||
sample rate and playback mode are part of the song itself, others are user preference
|
||||
|
||||
|
@ -37,6 +37,7 @@ start with playback mode Bytebeat, sample rate 8000, and this code:
|
|||
```js
|
||||
t
|
||||
```
|
||||
|
||||
you should get a low pitch sawtooth wave (sawtooth being the diagonal spike shape on the oscillioscope, note that one side is diagonal and the other vertical)
|
||||
|
||||
the letter `t` here represents the time variable, this code is just outputting the time.
|
||||
|
@ -64,14 +65,12 @@ by multiplying t by larger numbers you can get higher pitches.
|
|||
note that at high values like 34 the wrapping doesn't quite line up anymore and you can both see and hear issues, this is caused by aliasing.
|
||||
if you go extremely high multiples like 255 the pitch goes down again because it wraps mostly back to where it was before, at 256 it wraps all the way back to the start.
|
||||
|
||||
|
||||
```js
|
||||
t*t/300
|
||||
```
|
||||
|
||||
last to look at here is just increasing pitch, note that after the pitch gets high enough the pitch starts dropping again due to aliasing.
|
||||
|
||||
|
||||
at this point you may want to read up on [javascript operators](https://www.w3schools.com/jsref/jsref_operators.asp).
|
||||
important here currently are arithmetic operators, comparison operators, and logical operators.
|
||||
you may want to also check operator precedence to get an idea of when parenthesis are needed or not
|
||||
|
@ -295,20 +294,17 @@ something to note here is that the pitch of the sine wave is so low you can't ev
|
|||
something you might be wondering is why we're changing the phase and not the pitch, this is for two reasons:
|
||||
|
||||
1. changing the phase changes the pitch
|
||||
|
||||
pitch is just change of phase, so every part of the sin wave with a steep slope is an increase or decrease in pitch
|
||||
|
||||
pitch is just change of phase, so every part of the sin wave with a steep slope is an increase or decrease in pitch
|
||||
2. trying to change the pitch doesn't even work
|
||||
```js
|
||||
(t*2*(1+sin(t/300)/64))%128
|
||||
```
|
||||
|
||||
```js
|
||||
(t*2*(1+sin(t/300)/64))%128
|
||||
```
|
||||
reset the time to 0 and listen to this formula, the vibrato just keeps getting stronger as time goes on.
|
||||
this is because trying to change the pitch like this does change the speed, but it doesn't keep the phase.
|
||||
|
||||
reset the time to 0 and listen to this formula, the vibrato just keeps getting stronger as time goes on.
|
||||
this is because trying to change the pitch like this does change the speed, but it doesn't keep the phase.
|
||||
|
||||
to change the pitch correctly here we would need to either store the phase (annoying and can cause various issues),
|
||||
or use an infinite series of terms to manage rate of change of pitch, rate of change of rate of change of pitch, and so on (literally impossible) (hint #2 again).
|
||||
to change the pitch correctly here we would need to either store the phase (annoying and can cause various issues),
|
||||
or use an infinite series of terms to manage rate of change of pitch, rate of change of rate of change of pitch, and so on (literally impossible) (hint #2 again).
|
||||
|
||||
just modulate the phase, not only does it work but it allows doing more than modulating pitch can.
|
||||
|
||||
|
@ -392,13 +388,10 @@ sync with sawtooth fm
|
|||
|
||||
inverted sawtooth pulse
|
||||
|
||||
|
||||
wrapping with & operator always wraps in positive range and truncates,
|
||||
however note that it can only wrap for powers of 2, and operator precedence is different.
|
||||
this can save on characters in many situations.
|
||||
|
||||
|
||||
|
||||
arrays, strings, charCodeAt, fromCharCode
|
||||
|
||||
variables, comma operator
|
||||
|
@ -414,7 +407,7 @@ you'll more likely recognize this from physics
|
|||
|
||||
d = cycles (phase)
|
||||
v = cycles / s (Hz)
|
||||
a = cycles / s**2 (rate of change of Hz)
|
||||
a = cycles / s\*\*2 (rate of change of Hz)
|
||||
|
||||
this allows pitch shifting without messing up phase (which often messes up the pitch shifting in the first place)
|
||||
|
||||
|
|
44
README.md
44
README.md
|
@ -1,23 +1,26 @@
|
|||
# bytebeat-composer
|
||||
|
||||
modern bytebeat player with a library of many formulas from around the internet.
|
||||
|
||||
originally forked from [StephanShi's website](https://github.com/SthephanShinkufag/bytebeat-composer) to fix bugs and add features, now maintained independently.
|
||||
|
||||
afaik this was the first bytebeat program that didn't have any major playback bugs (the two common ones are being unable to access functions like `escape`, and editing strings like `"sin"`).
|
||||
this program also works well with storing persistent variables, in this example `b` is used to store persistent variables
|
||||
this program also works well with storing persistent variables, in this example `b` is used to store persistent variables:
|
||||
|
||||
```js
|
||||
this.b??={a:0,b:0}, // this, window, and globalThis are all the same in this context
|
||||
w=((t/(+"8654"[t>>11&3]+(t>>15&1))/10%1>.5)+1.5)*64,
|
||||
c=sin(t/2e3)/6+.3,
|
||||
b.b+=c*((b.a+=c*(w-b.a+(b.a-b.b)/.7))-b.b)
|
||||
```
|
||||
all iterable variables are deleted when the bytebeat is input, so variables between bytebeats don't conflict
|
||||
|
||||
Longline Theory and Information Theory are played correctly since a signed bytebeat mode has been added
|
||||
all iterable variables are deleted when the bytebeat is input, so variables between bytebeats don't conflict.
|
||||
|
||||
syntax highlighting has been added, with a good amount of useful settings but nothing intrusive
|
||||
Longline Theory and Information Theory are played correctly since a signed bytebeat mode has been added.
|
||||
|
||||
stereo is supported by returning an array
|
||||
syntax highlighting has been added, with a good amount of useful settings but nothing intrusive.
|
||||
|
||||
stereo is supported by returning an array.
|
||||
|
||||
## warning
|
||||
|
||||
|
@ -25,25 +28,28 @@ this website runs arbitrary code!
|
|||
|
||||
i've taken many security measures, but i can't guarantee what i've done is foolproof.
|
||||
as far as i can tell, this website should be secure, but this doesn't prevent:
|
||||
|
||||
- taking advantage of browser security vulnerabilities
|
||||
- locking up the audio thread, making controls not work (volume still works, and the page can be refreshed)
|
||||
- anything else an AudioWorklet could do that i don't know about (i really don't know that much about security)
|
||||
|
||||
on a secure browser the website _should_ be safe, but i can't guarantee anything.
|
||||
If i've messed up anywhere then results could be much worse
|
||||
If i've messed up anywhere then results could be much worse.
|
||||
|
||||
to judge yourself, these are the security measures i've taken:
|
||||
|
||||
- input code is ran in an audio worklet (note that the code has access to the global scope)
|
||||
- most iterable global variables are deleted
|
||||
- objects and prototypes of objects on the global scope are frozen
|
||||
- variables remaining on the global scope are made unwritable and unconfigurable
|
||||
- variables remaining on the global scope are made unwritable and unconfigurable
|
||||
|
||||
## embedding
|
||||
|
||||
https://bytebeat.ficial.io/embed is an embeddable version of the page, designed to be used in other projects.
|
||||
it doesn't have the library, doesn't save settings, and can recieve commands via `postMessage`
|
||||
it doesn't have the library, doesn't save settings, and can recieve commands via `postMessage`.
|
||||
|
||||
command format:
|
||||
|
||||
```js
|
||||
{
|
||||
show: { // show / hide webpage elements
|
||||
|
@ -68,6 +74,7 @@ command format:
|
|||
```
|
||||
|
||||
any messages recieved will be in this format:
|
||||
|
||||
```js
|
||||
{
|
||||
song: { // sent on getSong
|
||||
|
@ -84,10 +91,10 @@ if any previously working links stop working, LET ME KNOW. link compatibility is
|
|||
if i'm unavalible or you're in a hurry, you can decode the links manually:
|
||||
|
||||
- links prefixed with `#v3b64` are the oldest, to decode:
|
||||
1. remove the prefix
|
||||
2. convert from base 64 with atob
|
||||
4. inflate to string with deflate (you can use a tool like fflate or pako)
|
||||
5. parse with JSON
|
||||
1. remove the prefix
|
||||
2. convert from base 64 with atob
|
||||
3. inflate to string with deflate (you can use a tool like fflate or pako)
|
||||
4. parse with JSON
|
||||
- links prefixed with `#v4` have essentially the same process. the only differences are the prefix and the absence of base64 padding.
|
||||
|
||||
newer formats are complicated, so i'll only provide commit hashes and the code locations.
|
||||
|
@ -96,16 +103,13 @@ newer formats are complicated, so i'll only provide commit hashes and the code l
|
|||
- `#6` commit a36406d, src/url/mod.ts. this version was reverted because the urls broke markdown
|
||||
- `#5` after commit a36406d, src/url/mod.ts
|
||||
|
||||
|
||||
|
||||
## building
|
||||
|
||||
install pnpm
|
||||
|
||||
```sh
|
||||
pnpm i --prod
|
||||
pnpm run build
|
||||
```
|
||||
- install pnpm
|
||||
- ```sh
|
||||
pnpm i --prod
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
output is in \_site, you can start a webserver there.
|
||||
|
||||
|
|
|
@ -20,11 +20,7 @@ module.exports = eleventyConfig => {
|
|||
eleventyConfig.on("eleventy.after", async ({ dir, results, runMode, outputMode }) => {
|
||||
await Promise.all([
|
||||
esbuild.build({
|
||||
entryPoints: [
|
||||
`src/style.css`,
|
||||
`src/bytebeat.ts`,
|
||||
`src/embed.ts`,
|
||||
],
|
||||
entryPoints: [`src/style.css`, `src/bytebeat.ts`, `src/embed.ts`],
|
||||
outdir: output,
|
||||
format: "esm",
|
||||
bundle: true,
|
||||
|
@ -34,9 +30,7 @@ module.exports = eleventyConfig => {
|
|||
//write: serve,
|
||||
}),
|
||||
esbuild.build({
|
||||
entryPoints: [
|
||||
`src/audio-worklet/audio-worklet.ts`,
|
||||
],
|
||||
entryPoints: [`src/audio-worklet/audio-worklet.ts`],
|
||||
outdir: output,
|
||||
format: "esm",
|
||||
bundle: true,
|
||||
|
|
|
@ -6,6 +6,7 @@ no player has all of these features yet but i considered everything that seemed
|
|||
i will not change anything already defined in the format because i already made my urls and backwards compatibility should stay forever.
|
||||
|
||||
some pseudo javascript to show how the format works:
|
||||
|
||||
```js
|
||||
mode & 0x80 ? /* code is statements */ : /* code is an expression */
|
||||
mode & 0x40 ? /* returns a function */ : /* returns a number */
|
||||
|
|
|
@ -5,12 +5,12 @@ import type { DrawSample } from "../oscillioscope.ts";
|
|||
declare abstract class AudioWorkletProcessor {
|
||||
readonly port: MessagePort;
|
||||
constructor(options?: {
|
||||
numberOfInputs?: number,
|
||||
numberOfOutputs?: number,
|
||||
outputChannelCount: number[],
|
||||
numberOfInputs?: number;
|
||||
numberOfOutputs?: number;
|
||||
outputChannelCount: number[];
|
||||
// i don't understand these ones
|
||||
parameterData?: unknown,
|
||||
processorOptions?: unknown,
|
||||
parameterData?: unknown;
|
||||
processorOptions?: unknown;
|
||||
});
|
||||
abstract process(
|
||||
_inputs: Float32Array[][],
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import { EditorState } from "@codemirror/state";
|
||||
import { EditorView, keymap, highlightSpecialChars } from "@codemirror/view";
|
||||
import { history, historyKeymap, defaultKeymap, insertNewline, indentLess } from "@codemirror/commands";
|
||||
import {
|
||||
history,
|
||||
historyKeymap,
|
||||
defaultKeymap,
|
||||
insertNewline,
|
||||
indentLess,
|
||||
} from "@codemirror/commands";
|
||||
import { searchKeymap, highlightSelectionMatches } from "@codemirror/search";
|
||||
import { indentUnit, bracketMatching, syntaxHighlighting } from "@codemirror/language";
|
||||
import { javascript } from "@codemirror/lang-javascript";
|
||||
import { classHighlighter } from "@lezer/highlight";
|
||||
|
||||
function createCodemirror(inputListener?: (() => void)) {
|
||||
function createCodemirror(inputListener?: () => void) {
|
||||
const editor = new EditorView({
|
||||
state: EditorState.create({
|
||||
extensions: [
|
||||
|
|
|
@ -9,15 +9,18 @@ class CodeEditor {
|
|||
const textarea = document.getElementById("code-editor") as HTMLTextAreaElement;
|
||||
initTextarea(editCallback, textarea);
|
||||
this.getCode = () => textarea.value;
|
||||
this.setCode = v => {textarea.value = v as string};
|
||||
|
||||
this.setCode = v => {
|
||||
textarea.value = v as string;
|
||||
};
|
||||
|
||||
// codemirror takes a long time to load, so import it late, then replace the textarea
|
||||
import("./codemirror.ts").then(c => {
|
||||
const codemirror = c.replace(editCallback, textarea);
|
||||
this.getCode = () => codemirror.state.doc.toString();
|
||||
this.setCode = v => codemirror.dispatch({
|
||||
changes: { from: 0, to: codemirror.state.doc.length, insert: v },
|
||||
});
|
||||
this.setCode = v =>
|
||||
codemirror.dispatch({
|
||||
changes: { from: 0, to: codemirror.state.doc.length, insert: v },
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
function f32ToRound10(value: number): number {
|
||||
// this is stupid but it works for numbers less
|
||||
// than 10 digits on one side of the decimal point
|
||||
const p7 = +(value.toPrecision(7));
|
||||
// this is stupid but it works for numbers less
|
||||
// than 10 digits on one side of the decimal point
|
||||
const p7 = +value.toPrecision(7);
|
||||
if (Math.fround(p7) === value) {
|
||||
return p7
|
||||
return p7;
|
||||
}
|
||||
const p8 = +(value.toPrecision(8));
|
||||
const p8 = +value.toPrecision(8);
|
||||
if (Math.fround(p8) === value) {
|
||||
return p8
|
||||
return p8;
|
||||
}
|
||||
return +(value.toPrecision(9));
|
||||
return +value.toPrecision(9);
|
||||
|
||||
// for the range that sampleRate uses:
|
||||
// 62677722 numbers needs precision 7
|
||||
|
|
|
@ -23,11 +23,7 @@
|
|||
<main id="content">
|
||||
<section class="container-fixed">
|
||||
<div id="code-editor-container">
|
||||
<textarea
|
||||
id="code-editor"
|
||||
aria-label="Code editor"
|
||||
spellcheck="false"
|
||||
></textarea>
|
||||
<textarea id="code-editor" aria-label="Code editor" spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div id="controls">
|
||||
<span class="control-group control-time" id="control-time">
|
||||
|
@ -36,11 +32,7 @@
|
|||
id="control-time-unit"
|
||||
onclick="bytebeat.changeTimeUnit();"
|
||||
>
|
||||
<label
|
||||
id="control-time-unit-label"
|
||||
for="control-time-value"
|
||||
>t</label
|
||||
>
|
||||
<label id="control-time-unit-label" for="control-time-value">t</label>
|
||||
</button>
|
||||
<input
|
||||
title="Time value"
|
||||
|
@ -52,11 +44,7 @@
|
|||
/>
|
||||
</span>
|
||||
<span class="control-group control-time buttons">
|
||||
<button
|
||||
title="Restart"
|
||||
id="control-restart"
|
||||
onclick="bytebeat.resetTime();"
|
||||
>
|
||||
<button title="Restart" id="control-restart" onclick="bytebeat.resetTime();">
|
||||
⏮︎
|
||||
</button>
|
||||
<button
|
||||
|
@ -73,11 +61,7 @@
|
|||
>
|
||||
⏴︎
|
||||
</button>
|
||||
<button
|
||||
title="Pause"
|
||||
id="control-pause"
|
||||
onclick="bytebeat.togglePlay(false);"
|
||||
>
|
||||
<button title="Pause" id="control-pause" onclick="bytebeat.togglePlay(false);">
|
||||
⏸︎
|
||||
</button>
|
||||
<button
|
||||
|
@ -115,11 +99,7 @@
|
|||
>
|
||||
+
|
||||
</button>
|
||||
<button
|
||||
title="Zoom out"
|
||||
id="control-scaleup"
|
||||
onclick="bytebeat.changeScale(1);"
|
||||
>
|
||||
<button title="Zoom out" id="control-scaleup" onclick="bytebeat.changeScale(1);">
|
||||
-
|
||||
</button>
|
||||
</span>
|
||||
|
@ -156,12 +136,8 @@
|
|||
onblur="this.value||=this.placeholder;this.placeholder=''"
|
||||
onchange="bytebeat.setSampleRate(+this.value); bytebeat.refreshCode();"
|
||||
/><span class="text"
|
||||
><label for="control-sample-rate" class="control-song"
|
||||
>Hz</label
|
||||
>
|
||||
<label
|
||||
for="control-sample-rate-divisor"
|
||||
class="control-playback"
|
||||
><label for="control-sample-rate" class="control-song">Hz</label>
|
||||
<label for="control-sample-rate-divisor" class="control-playback"
|
||||
>/</label
|
||||
></span
|
||||
><input
|
||||
|
@ -207,10 +183,7 @@
|
|||
<!-- SVG BUTTONS -->
|
||||
<!-- TODO: create svgs for all controls-->
|
||||
<div id="svg-icons" style="height: 0; width: 0; overflow: hidden">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<symbol viewBox="0 0 32 32" id="symbol-play">
|
||||
<path
|
||||
d="m23 14.3-9-5.2c-1.3-.8-3 .2-3 1.7v10.4c0 1.5 1.7 2.5 3 1.7l9-5.2c1.3-.7 1.3-2.7 0-3.4z"
|
||||
|
|
|
@ -22,10 +22,7 @@ html(data-embed lang="en")
|
|||
textarea#code-editor(spellcheck="false" aria-label="Code editor")
|
||||
#controls
|
||||
span#control-time.control-group.control-time
|
||||
button#control-time-unit(
|
||||
onclick="bytebeat.changeTimeUnit();"
|
||||
title="Time unit"
|
||||
)
|
||||
button#control-time-unit(onclick="bytebeat.changeTimeUnit();" title="Time unit")
|
||||
label#control-time-unit-label(for="control-time-value") t
|
||||
input#control-time-value(
|
||||
onchange="bytebeat.setByteSample(bytebeat.convertFromUnit(+this.value)); this.value = '';"
|
||||
|
@ -64,14 +61,8 @@ html(data-embed lang="en")
|
|||
title="Volume"
|
||||
)
|
||||
span.control-group.control-view.buttons.buttons-zoom
|
||||
button#control-scaledown(
|
||||
onclick="bytebeat.changeScale(-1);"
|
||||
title="Zoom in"
|
||||
) +
|
||||
button#control-scaleup(
|
||||
onclick="bytebeat.changeScale(1);"
|
||||
title="Zoom out"
|
||||
) -
|
||||
button#control-scaledown(onclick="bytebeat.changeScale(-1);" title="Zoom in") +
|
||||
button#control-scaleup(onclick="bytebeat.changeScale(1);" title="Zoom out") -
|
||||
//
|
||||
<span class="control-group control-record buttons">
|
||||
<button title="Share" onclick="">🔗︎</button>
|
||||
|
@ -135,10 +126,7 @@ html(data-embed lang="en")
|
|||
// SVG BUTTONS
|
||||
// TODO: create svgs for all controls
|
||||
#svg-icons(style="height: 0; width: 0; overflow: hidden")
|
||||
svg(
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
)
|
||||
svg(xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg")
|
||||
symbol#symbol-play(viewBox="0 0 32 32")
|
||||
path(
|
||||
d="m23 14.3-9-5.2c-1.3-.8-3 .2-3 1.7v10.4c0 1.5 1.7 2.5 3 1.7l9-5.2c1.3-.7 1.3-2.7 0-3.4z"
|
||||
|
|
|
@ -18,46 +18,37 @@ html(lang="en")
|
|||
| (t*(1+(5&t>>10))*(3+(t>>17&1?(2^2&t>>14)/3:3&(t>>13)+1))>>(3&t>>9))&(t&4096?(t*(t^t%9)|t>>3)>>1:255)
|
||||
#controls
|
||||
span#control-time.control-group.control-time
|
||||
button#control-time-unit(
|
||||
title="Time unit"
|
||||
onclick="bytebeat.changeTimeUnit();"
|
||||
)
|
||||
button#control-time-unit(title="Time unit" onclick="bytebeat.changeTimeUnit()")
|
||||
label#control-time-unit-label(for="control-time-value") t
|
||||
input#control-time-value(
|
||||
onchange="bytebeat.setByteSample(bytebeat.convertFromUnit(+this.value)); this.value = '';"
|
||||
onchange="bytebeat.setByteSample(bytebeat.convertFromUnit(+this.value)); this.value = ''"
|
||||
style="width: 8em"
|
||||
placeholder="0"
|
||||
type="number"
|
||||
title="Time value"
|
||||
)
|
||||
span.control-group.control-time.buttons
|
||||
button#control-restart(
|
||||
onclick="bytebeat.resetTime();"
|
||||
title="Restart"
|
||||
) ⏮︎
|
||||
button#control-restart(onclick="bytebeat.resetTime()" title="Restart") ⏮︎
|
||||
button#control-fr(
|
||||
onclick="bytebeat.setPlaySpeed(-4); bytebeat.togglePlay(true);"
|
||||
onclick="bytebeat.setPlaySpeed(-4); bytebeat.togglePlay(true)"
|
||||
title="Fast reverse"
|
||||
) ⏪︎
|
||||
button#control-reverse(
|
||||
onclick="bytebeat.setPlaySpeed(-1); bytebeat.togglePlay(true);"
|
||||
onclick="bytebeat.setPlaySpeed(-1); bytebeat.togglePlay(true)"
|
||||
title="Reverse"
|
||||
) ⏴︎
|
||||
button#control-pause(
|
||||
onclick="bytebeat.togglePlay(false);"
|
||||
title="Pause"
|
||||
) ⏸︎
|
||||
button#control-pause(onclick="bytebeat.togglePlay(false)" title="Pause") ⏸︎
|
||||
button#control-play(
|
||||
onclick="bytebeat.setPlaySpeed(1); bytebeat.togglePlay(true);"
|
||||
onclick="bytebeat.setPlaySpeed(1); bytebeat.togglePlay(true)"
|
||||
title="Play"
|
||||
) ⏵︎
|
||||
button#control-ff(
|
||||
onclick="bytebeat.setPlaySpeed(4); bytebeat.togglePlay(true);"
|
||||
onclick="bytebeat.setPlaySpeed(4); bytebeat.togglePlay(true)"
|
||||
title="Fast Forward"
|
||||
) ⏩︎
|
||||
span.control-group.control-playback
|
||||
input#control-volume(
|
||||
oninput="bytebeat.setVolume();"
|
||||
oninput="bytebeat.setVolume()"
|
||||
value="0.6"
|
||||
step="any"
|
||||
max="1"
|
||||
|
@ -67,14 +58,8 @@ html(lang="en")
|
|||
style="width: 8em"
|
||||
)
|
||||
span.control-group.control-view.buttons
|
||||
button#control-scaledown(
|
||||
onclick="bytebeat.changeScale(-1);"
|
||||
title="Zoom in"
|
||||
) +
|
||||
button#control-scaleup(
|
||||
onclick="bytebeat.changeScale(1);"
|
||||
title="Zoom out"
|
||||
) -
|
||||
button#control-scaledown(onclick="bytebeat.changeScale(-1)" title="Zoom in") +
|
||||
button#control-scaleup(onclick="bytebeat.changeScale(1)" title="Zoom out") -
|
||||
//
|
||||
span.control-group.control-record.buttons
|
||||
button(title="Share" onclick="") 🔗︎
|
||||
|
@ -83,7 +68,7 @@ html(lang="en")
|
|||
button(title="Record" onclick="") ⏺︎
|
||||
span.control-group.control-song
|
||||
select#control-song-mode(
|
||||
onchange="bytebeat.setPlaybackMode(this.value);"
|
||||
onchange="bytebeat.setPlaybackMode(this.value)"
|
||||
title="Playback mode"
|
||||
)
|
||||
option(value="Bytebeat" selected) Bytebeat
|
||||
|
@ -92,7 +77,7 @@ html(lang="en")
|
|||
option(value="Funcbeat") Funcbeat
|
||||
span.control-group
|
||||
input#control-sample-rate.control-song.control-round-right(
|
||||
onchange="bytebeat.setSampleRate(+this.value); bytebeat.refreshCode();"
|
||||
onchange="bytebeat.setSampleRate(+this.value); bytebeat.refreshCode()"
|
||||
onblur="this.value||=this.placeholder;this.placeholder=''"
|
||||
onfocus="this.placeholder=this.value;this.value=''"
|
||||
style="width: 6em"
|
||||
|
@ -107,7 +92,7 @@ html(lang="en")
|
|||
label.control-song(for="control-sample-rate") Hz
|
||||
label.control-playback(for="control-sample-rate-divisor") /
|
||||
input#control-sample-rate-divisor.control-playback.control-round-left.control-round-right(
|
||||
onchange="bytebeat.setSampleRateDivisor(+this.value); bytebeat.refreshCode();"
|
||||
onchange="bytebeat.setSampleRateDivisor(+this.value); bytebeat.refreshCode()"
|
||||
style="width: 3em"
|
||||
value="1"
|
||||
step="1"
|
||||
|
@ -124,9 +109,7 @@ html(lang="en")
|
|||
option(value="44100")
|
||||
option(value="48000")
|
||||
#error
|
||||
#canvas-container(
|
||||
onclick="bytebeat.setPlaySpeed(1); bytebeat.togglePlay()"
|
||||
)
|
||||
#canvas-container(onclick="bytebeat.setPlaySpeed(1); bytebeat.togglePlay()")
|
||||
canvas#canvas-main(height="256" width="1024" aria-label="Oscillioscope")
|
||||
#canvas-timecursor
|
||||
#canvas-toggleplay.canvas-toggleplay-show
|
||||
|
@ -174,20 +157,11 @@ html(lang="en")
|
|||
href="https://countercomplex.blogspot.com.au/search/label/algorithmic%20music"
|
||||
) Blog posts #2
|
||||
li
|
||||
a(
|
||||
target="_blank"
|
||||
href="https://www.youtube.com/watch?v=GtQdIYUtAHg"
|
||||
) YouTube video #1
|
||||
a(target="_blank" href="https://www.youtube.com/watch?v=GtQdIYUtAHg") YouTube video #1
|
||||
li
|
||||
a(
|
||||
target="_blank"
|
||||
href="https://www.youtube.com/watch?v=qlrs2Vorw2Y"
|
||||
) YouTube video #2
|
||||
a(target="_blank" href="https://www.youtube.com/watch?v=qlrs2Vorw2Y") YouTube video #2
|
||||
li
|
||||
a(
|
||||
target="_blank"
|
||||
href="https://www.youtube.com/watch?v=tCRPUv8V22o"
|
||||
) YouTube video #3
|
||||
a(target="_blank" href="https://www.youtube.com/watch?v=tCRPUv8V22o") YouTube video #3
|
||||
figure.figure-list
|
||||
figcaption Online JavaScript players:
|
||||
ul
|
||||
|
@ -201,10 +175,7 @@ html(lang="en")
|
|||
li
|
||||
a(target="_blank" href="https://entropedia.co.uk/generative_music") by Paul Hayes
|
||||
li
|
||||
a(
|
||||
target="_blank"
|
||||
href="https://wurstcaptures.untergrund.net/music"
|
||||
) by Bemmu and Rarefluid
|
||||
a(target="_blank" href="https://wurstcaptures.untergrund.net/music") by Bemmu and Rarefluid
|
||||
section
|
||||
p
|
||||
| This webpage has a collection of bytebeat music found by
|
||||
|
@ -282,17 +253,11 @@ html(lang="en")
|
|||
footer
|
||||
a.link(target="_blank" href="https://dollchan.net/btb") Dollchan Discussion board
|
||||
br
|
||||
a.link(
|
||||
target="_blank"
|
||||
href="https://git.disroot.org/SArpnt/bytebeat-composer"
|
||||
) Source code
|
||||
a.link(target="_blank" href="https://git.disroot.org/SArpnt/bytebeat-composer") Source code
|
||||
// SVG BUTTONS
|
||||
// TODO: create svgs for all controls
|
||||
#svg-icons(style="height: 0; width: 0; overflow: hidden")
|
||||
svg(
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
)
|
||||
svg(xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg")
|
||||
symbol#symbol-play(viewBox="0 0 32 32")
|
||||
path(
|
||||
d="m23 14.3-9-5.2c-1.3-.8-3 .2-3 1.7v10.4c0 1.5 1.7 2.5 3 1.7l9-5.2c1.3-.7 1.3-2.7 0-3.4z"
|
||||
|
|
|
@ -5,10 +5,7 @@ function stripEntryToSong(entry: Entry) {
|
|||
const { sampleRate, mode } = entry;
|
||||
return { sampleRate, mode };
|
||||
}
|
||||
function stripInlineEntryToSong(
|
||||
entry: Readonly<InlineEntry>,
|
||||
codeType: keyof InlineEntry,
|
||||
) {
|
||||
function stripInlineEntryToSong(entry: Readonly<InlineEntry>, codeType: keyof InlineEntry) {
|
||||
const { sampleRate, mode } = entry;
|
||||
return { code: entry[codeType], sampleRate, mode };
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ const lbl = Array(20)
|
|||
* converts data into base89, using all the valid characters for a url anchor.
|
||||
* this allows incredibly small urls, but many of these characters
|
||||
* break markdown and other common post formatting.
|
||||
*
|
||||
*
|
||||
* bitIndex is the first bit that into89 will read from and encode,
|
||||
* and it'll continue until the end of the array.
|
||||
* use bitIndex if you want to trim less than 8 bits off the data.
|
||||
|
|
|
@ -142,7 +142,7 @@ async function setUrlData({ code, mode, sampleRate }: Song) {
|
|||
* samplerates out of the range won't get stored correctly at all
|
||||
* you can do Math.min(Math.max(Math.fround(sampleRate), 2), 2 ** 24 - 1)
|
||||
* to get any number within the correct range
|
||||
*
|
||||
*
|
||||
* this function sets the window hash directly, it doesn't return a string
|
||||
*/
|
||||
async function setUrlData({ code, mode, sampleRate }: Song) {
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
"noEmit": true,
|
||||
"target": "esnext",
|
||||
"strict": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"types": ["jest"]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue