2023-12-25 18:51:35 +01:00
|
|
|
doctype html
|
|
|
|
html(lang="en")
|
|
|
|
head
|
|
|
|
meta(charset="utf-8")
|
|
|
|
meta(name="viewport" content="width=device-width,initial-scale=1")
|
|
|
|
meta(name="description" content="JS algorithmic music generator")
|
|
|
|
meta(name="author" content="SArpnt")
|
|
|
|
title Bytebeat composer
|
|
|
|
link(href="/favicon.png" rel="shortcut icon")
|
|
|
|
link(href="/style.css" type="text/css" rel="stylesheet")
|
2024-03-14 06:49:35 +01:00
|
|
|
script(src="/bytebeat.js" defer type="module")
|
2023-12-28 04:37:48 +01:00
|
|
|
link(rel="modulepreload" as="audioworklet" href="/audio-worklet.js")
|
2023-12-25 18:51:35 +01:00
|
|
|
body
|
|
|
|
main#content
|
|
|
|
section.container-fixed
|
|
|
|
#code-editor-container
|
|
|
|
textarea#code-editor(aria-label="Code editor" spellcheck="false")
|
|
|
|
| (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
|
2024-04-17 07:37:51 +02:00
|
|
|
button#control-time-unit(title="Time unit" onclick="bytebeat.changeTimeUnit()")
|
2023-12-25 18:51:35 +01:00
|
|
|
label#control-time-unit-label(for="control-time-value") t
|
|
|
|
input#control-time-value(
|
2024-04-17 07:37:51 +02:00
|
|
|
onchange="bytebeat.setByteSample(bytebeat.convertFromUnit(+this.value)); this.value = ''"
|
2024-08-02 05:40:17 +02:00
|
|
|
style="width:8em"
|
2023-12-25 18:51:35 +01:00
|
|
|
placeholder="0"
|
|
|
|
type="number"
|
|
|
|
title="Time value"
|
|
|
|
)
|
|
|
|
span.control-group.control-time.buttons
|
2024-04-17 07:37:51 +02:00
|
|
|
button#control-restart(onclick="bytebeat.resetTime()" title="Restart") ⏮︎
|
2023-12-25 18:51:35 +01:00
|
|
|
button#control-fr(
|
2024-04-17 07:37:51 +02:00
|
|
|
onclick="bytebeat.setPlaySpeed(-4); bytebeat.togglePlay(true)"
|
2023-12-25 18:51:35 +01:00
|
|
|
title="Fast reverse"
|
2023-12-25 21:56:34 +01:00
|
|
|
) ⏪︎
|
2023-12-25 18:51:35 +01:00
|
|
|
button#control-reverse(
|
2024-04-17 07:37:51 +02:00
|
|
|
onclick="bytebeat.setPlaySpeed(-1); bytebeat.togglePlay(true)"
|
2023-12-25 18:51:35 +01:00
|
|
|
title="Reverse"
|
2023-12-25 21:56:34 +01:00
|
|
|
) ⏴︎
|
2024-04-17 07:37:51 +02:00
|
|
|
button#control-pause(onclick="bytebeat.togglePlay(false)" title="Pause") ⏸︎
|
2023-12-25 18:51:35 +01:00
|
|
|
button#control-play(
|
2024-04-17 07:37:51 +02:00
|
|
|
onclick="bytebeat.setPlaySpeed(1); bytebeat.togglePlay(true)"
|
2023-12-25 18:51:35 +01:00
|
|
|
title="Play"
|
2023-12-25 21:56:34 +01:00
|
|
|
) ⏵︎
|
2023-12-25 18:51:35 +01:00
|
|
|
button#control-ff(
|
2024-04-17 07:37:51 +02:00
|
|
|
onclick="bytebeat.setPlaySpeed(4); bytebeat.togglePlay(true)"
|
2023-12-25 18:51:35 +01:00
|
|
|
title="Fast Forward"
|
2023-12-25 21:56:34 +01:00
|
|
|
) ⏩︎
|
2023-12-25 18:51:35 +01:00
|
|
|
span.control-group.control-playback
|
|
|
|
input#control-volume(
|
2024-04-17 07:37:51 +02:00
|
|
|
oninput="bytebeat.setVolume()"
|
2023-12-25 18:51:35 +01:00
|
|
|
value="0.6"
|
|
|
|
step="any"
|
|
|
|
max="1"
|
|
|
|
min="0"
|
|
|
|
type="range"
|
|
|
|
title="Volume"
|
2024-08-02 05:40:17 +02:00
|
|
|
style="width:8em"
|
2023-12-25 18:51:35 +01:00
|
|
|
)
|
|
|
|
span.control-group.control-view.buttons
|
2024-04-17 07:37:51 +02:00
|
|
|
button#control-scaledown(onclick="bytebeat.changeScale(-1)" title="Zoom in") +
|
|
|
|
button#control-scaleup(onclick="bytebeat.changeScale(1)" title="Zoom out") -
|
2023-12-25 18:51:35 +01:00
|
|
|
//
|
|
|
|
span.control-group.control-record.buttons
|
|
|
|
button(title="Share" onclick="") 🔗︎
|
|
|
|
button(title="Download" onclick="") 📥︎
|
|
|
|
button(title="Upload" onclick="") 📤︎
|
|
|
|
button(title="Record" onclick="") ⏺︎
|
|
|
|
span.control-group.control-song
|
|
|
|
select#control-song-mode(
|
2024-08-02 05:40:17 +02:00
|
|
|
onchange="bytebeat.setSongMode(this.value); bytebeat.refresh()"
|
2023-12-25 18:51:35 +01:00
|
|
|
title="Playback mode"
|
|
|
|
)
|
|
|
|
option(value="Bytebeat" selected) Bytebeat
|
|
|
|
option(value="Signed Bytebeat") Signed Bytebeat
|
|
|
|
option(value="Floatbeat") Floatbeat
|
|
|
|
option(value="Funcbeat") Funcbeat
|
|
|
|
span.control-group
|
2023-12-28 21:34:32 +01:00
|
|
|
input#control-sample-rate.control-song.control-round-right(
|
2024-08-02 05:07:45 +02:00
|
|
|
onchange="bytebeat.setSampleRate(+this.value); bytebeat.refresh()"
|
2023-12-25 18:51:35 +01:00
|
|
|
onblur="this.value||=this.placeholder;this.placeholder=''"
|
|
|
|
onfocus="this.placeholder=this.value;this.value=''"
|
2024-08-02 05:40:17 +02:00
|
|
|
style="width:6em"
|
2023-12-25 18:51:35 +01:00
|
|
|
value="8000"
|
|
|
|
list="samplerates"
|
|
|
|
step="any"
|
|
|
|
min="0"
|
|
|
|
type="number"
|
|
|
|
title="Sample rate"
|
|
|
|
)
|
|
|
|
span.text
|
2023-12-28 21:34:32 +01:00
|
|
|
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(
|
2024-08-02 05:07:45 +02:00
|
|
|
onchange="bytebeat.setSampleRateDivisor(+this.value); bytebeat.refresh()"
|
2023-12-25 18:51:35 +01:00
|
|
|
style="width: 3em"
|
|
|
|
value="1"
|
|
|
|
step="1"
|
|
|
|
min="1"
|
|
|
|
type="number"
|
|
|
|
title="Sample rate divisor"
|
|
|
|
)
|
|
|
|
datalist#samplerates
|
|
|
|
option(value="8000")
|
|
|
|
option(value="11025")
|
|
|
|
option(value="16000")
|
|
|
|
option(value="22050")
|
|
|
|
option(value="32000")
|
|
|
|
option(value="44100")
|
|
|
|
option(value="48000")
|
|
|
|
#error
|
2024-04-17 07:37:51 +02:00
|
|
|
#canvas-container(onclick="bytebeat.setPlaySpeed(1); bytebeat.togglePlay()")
|
2023-12-25 18:51:35 +01:00
|
|
|
canvas#canvas-main(height="256" width="1024" aria-label="Oscillioscope")
|
|
|
|
#canvas-timecursor
|
|
|
|
#canvas-toggleplay.canvas-toggleplay-show
|
|
|
|
svg#svg-canvas-toggleplay-play
|
|
|
|
use(xlink:href="#symbol-play")
|
|
|
|
svg#svg-canvas-toggleplay-pause
|
|
|
|
use(xlink:href="#symbol-pause")
|
|
|
|
section.container-scroll
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h1 Info — about bytebeat
|
2023-12-25 18:51:35 +01:00
|
|
|
article
|
|
|
|
section
|
2024-08-02 05:40:17 +02:00
|
|
|
p.
|
|
|
|
Bytebeat music (or one-liner music) was invented in
|
|
|
|
September 2011. Simple bytebeats are often a piece of
|
|
|
|
rhythmic and somewhat melodic music with no score, no
|
|
|
|
instruments, and no real oscillators. It's simply an
|
|
|
|
expression that defines a waveform as a function of
|
|
|
|
time, processed (usually) 8000 times per second,
|
|
|
|
resulting in an audible waveform with a 256-step
|
|
|
|
resolution from silence (0) to full amplitude (256). If
|
|
|
|
you put that formula into a program with a loop that
|
|
|
|
increments time variable (t), you can generate the
|
|
|
|
headerless unsigned 8 bit mono 8kHz audio stream on
|
|
|
|
output, like in this application. Since these directly
|
|
|
|
output a waveform, they have great performance in
|
|
|
|
compiled languages and can often be ran on even the
|
|
|
|
weakest embedded devices.
|
|
|
|
// TODO link the info.md
|
2023-12-25 18:51:35 +01:00
|
|
|
section
|
|
|
|
p
|
2023-12-25 21:56:34 +01:00
|
|
|
a(target="_blank" href="http://canonical.org/~kragen/bytebeat") History of bytebeat
|
2023-12-25 18:51:35 +01:00
|
|
|
figure.figure-list
|
|
|
|
figcaption Original blog posts and videos from Viznut:
|
|
|
|
ul
|
|
|
|
li
|
|
|
|
a(
|
|
|
|
target="_blank"
|
|
|
|
href="https://countercomplex.blogspot.com/2011/10/algorithmic-symphonies-from-one-line-of.html"
|
|
|
|
) Blog posts #1
|
|
|
|
li
|
|
|
|
a(
|
|
|
|
target="_blank"
|
|
|
|
href="https://countercomplex.blogspot.com.au/search/label/algorithmic%20music"
|
|
|
|
) Blog posts #2
|
|
|
|
li
|
2024-04-17 07:37:51 +02:00
|
|
|
a(target="_blank" href="https://www.youtube.com/watch?v=GtQdIYUtAHg") YouTube video #1
|
2023-12-25 18:51:35 +01:00
|
|
|
li
|
2024-04-17 07:37:51 +02:00
|
|
|
a(target="_blank" href="https://www.youtube.com/watch?v=qlrs2Vorw2Y") YouTube video #2
|
2023-12-25 18:51:35 +01:00
|
|
|
li
|
2024-04-17 07:37:51 +02:00
|
|
|
a(target="_blank" href="https://www.youtube.com/watch?v=tCRPUv8V22o") YouTube video #3
|
2023-12-25 18:51:35 +01:00
|
|
|
figure.figure-list
|
|
|
|
figcaption Online JavaScript players:
|
|
|
|
ul
|
|
|
|
li
|
|
|
|
a(target="_blank" href="https://dollchan.net/bytebeat") by SthephanShi
|
|
|
|
li
|
|
|
|
a(
|
|
|
|
target="_blank"
|
|
|
|
href="https://greggman.com/downloads/examples/html5bytebeat/html5bytebeat.html"
|
|
|
|
) by Greggman
|
|
|
|
li
|
2023-12-25 21:56:34 +01:00
|
|
|
a(target="_blank" href="https://entropedia.co.uk/generative_music") by Paul Hayes
|
2023-12-25 18:51:35 +01:00
|
|
|
li
|
2024-04-17 07:37:51 +02:00
|
|
|
a(target="_blank" href="https://wurstcaptures.untergrund.net/music") by Bemmu and Rarefluid
|
2023-12-25 18:51:35 +01:00
|
|
|
section
|
2024-08-02 05:40:17 +02:00
|
|
|
p.
|
|
|
|
This webpage has a collection of bytebeat music found by
|
|
|
|
SthephanShi, I may add my own compositions here too.
|
|
|
|
Playback modes are:
|
2023-12-25 18:51:35 +01:00
|
|
|
ul
|
2024-08-02 05:40:17 +02:00
|
|
|
li.
|
|
|
|
Bytebeat — audio output is from 0 to 255, values
|
|
|
|
outside this are wrapped, and non-integers are
|
|
|
|
floored.
|
|
|
|
li.
|
|
|
|
Signed Bytebeat — audio output is from -128 to
|
|
|
|
127, values outside this are wrapped, and
|
|
|
|
non-integers are floored. This is an uncommon format,
|
|
|
|
which comes from c allowing char to be signed or
|
|
|
|
unsigned depending on the compiler.
|
|
|
|
li.
|
|
|
|
Floatbeat — audio output is from -1.0 to 1.0,
|
|
|
|
values outside this are clipped. This allows higher
|
|
|
|
quality audio, and is common for other generative
|
|
|
|
music.
|
|
|
|
li.
|
|
|
|
Funcbeat — based on TinyRave, code is not an
|
|
|
|
expression, and is only ran once. The returned
|
|
|
|
function is ran with time in seconds, output is -1.0 to 1.0.
|
2023-12-25 18:51:35 +01:00
|
|
|
p
|
|
|
|
| This website is made by SArpnt, and is a fork of
|
2023-12-26 04:42:04 +01:00
|
|
|
|
|
2023-12-25 18:51:35 +01:00
|
|
|
a(target="_blank" href="https://dollchan.net/bytebeat") bytebeat-composer
|
2023-12-26 04:42:04 +01:00
|
|
|
|
|
2023-12-25 18:51:35 +01:00
|
|
|
| by
|
2023-12-26 04:42:04 +01:00
|
|
|
|
|
2023-12-25 18:51:35 +01:00
|
|
|
a(target="_blank" href="https://github.com/SthephanShinkufag") SthephanShi
|
|
|
|
| , which is a fork of
|
2023-12-26 04:42:04 +01:00
|
|
|
|
|
2023-12-25 21:56:34 +01:00
|
|
|
a(target="_blank" href="https://entropedia.co.uk/generative_music") 8-bit Generative Composer
|
2023-12-26 04:42:04 +01:00
|
|
|
|
|
2023-12-25 18:51:35 +01:00
|
|
|
| by
|
2023-12-26 04:42:04 +01:00
|
|
|
|
|
2023-12-25 18:51:35 +01:00
|
|
|
a(target="_blank" href="https://github.com/paulhayes") Paul Hayes
|
|
|
|
| .
|
|
|
|
details(open)
|
|
|
|
summary
|
|
|
|
h1 Library
|
|
|
|
#library
|
|
|
|
// TODO: generate these automatically with templates, and create template for individual songs
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h2 Classic — C compatible code
|
2023-12-25 18:51:35 +01:00
|
|
|
#library-classic
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h2 Compact JS — compact JavaScript code
|
2023-12-25 18:51:35 +01:00
|
|
|
#library-js-code
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h2 Big JS — big JavaScript code
|
2023-12-25 18:51:35 +01:00
|
|
|
#library-js-bigcode
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h2 Floatbeat — high quality output from -1.0 to 1.0
|
2023-12-25 18:51:35 +01:00
|
|
|
#library-floatbeat
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h2 Funcbeat — statement based
|
2023-12-25 18:51:35 +01:00
|
|
|
#library-funcbeat
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h2 SthephanShi — code SthephanShi created
|
2023-12-25 18:51:35 +01:00
|
|
|
#library-sthephanshi
|
|
|
|
details
|
|
|
|
summary
|
2023-12-25 21:56:34 +01:00
|
|
|
h2 SArpnt — code SArpnt created
|
2023-12-25 18:51:35 +01:00
|
|
|
#library-sarpnt
|
|
|
|
footer
|
2024-03-12 19:50:03 +01:00
|
|
|
a.link(target="_blank" href="https://dollchan.net/btb") Dollchan Discussion board
|
2023-12-25 18:51:35 +01:00
|
|
|
br
|
2024-04-17 07:37:51 +02:00
|
|
|
a.link(target="_blank" href="https://git.disroot.org/SArpnt/bytebeat-composer") Source code
|
2023-12-25 18:51:35 +01:00
|
|
|
// TODO: create svgs for all controls
|
2024-08-02 05:40:17 +02:00
|
|
|
svg(style="display:none" 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"
|
|
|
|
)
|
|
|
|
symbol#symbol-pause(viewBox="0 0 32 32")
|
|
|
|
path(
|
|
|
|
d="M12.5 23c-1.1 0-2-.9-2-2V11c0-1.1.9-2 2-2s2 .9 2 2v10c0 1.1-.9 2-2 2zm7 0c-1.1 0-2-.9-2-2V11c0-1.1.9-2 2-2s2 .9 2 2v10c0 1.1-.9 2-2 2z"
|
|
|
|
)
|