standard library - pannous/warp GitHub Wiki
Made by warp help --markdown from lib/*.warp: each module with its words, a word with the comment above it. A module comes with use <module>; the prelude needs none.
The prelude (notes/stdlib.md §8): words every program has without use; only those it calls come along. Each is name(parameters) := body (modules::prelude_word_arity reads the parameters); library_words maps other spellings and method forms onto them (isdigit(c), xs.first(), round(x, 2) → round_to)
first(xs)last(xs)-
first_items(xs, n): the first or last n items (fewer when xs has fewer):xs.first(3),first 3 of xs last_items(xs, n)-
round_to(x, places): x rounded to that many digits after the point -
mean(xs): the arithmetic mean, also spelled average replace(t, old, new)-
is_digit(c): ASCII character tests; a character compares by its code point is_alpha(c)is_alphanumeric(c)is_space(c)-
nearest(x, kind, limit = 0, within = 0): x as a fraction, by its continued fraction (src/real.rs computes it exactly for √2, π, … written in the program):within: 1e-6the first convergent that close, a limit the closest fraction whose denominator is at most that (Python's limit_denominator), neither the first convergent that is the same float; 0 means not given -
x as rationalof a float is the exact fraction of its printed digits:sqrt(2.0) as rationalis 14142135623730951/10000000000000000; nearest gives a short fraction close to it -
dict(pairs): Python's dict(pairs) (card python-stdlib): a map of [key value] pairs -
fromkeys(ks, value): Python's dict.fromkeys(ks, value) (card python-aliases): a map of each key with the one value -
popped_position(xs, i): Python's xs.pop(i) and m.pop(k) (card python-aliases, declaration_lowering removed_key): the element at the 0-based position i (-1 the last) or the value of the key k, and the list or map without it popped_item(x, k)popped_rest(x, k)-
cleared(x): Python's xs.clear() and m.clear() (card python-aliases, declaration_lowering cleared_collection): the empty list or map
Linear memory by its bytes (samples/wasm/wasm_interop.warp): memory.slice(ptr, end) reads the bytes ptr…end-1, memory.copy(bytes, ptr) writes them from ptr on; addresses are 0-based byte offsets
The standard library module net (notes/stdlib.md section 7): use net; fetch (GET) is a prelude word. post sends a text through the adapter std_io and gives the answer's text (ureq natively, a synchronous request in the browser)
post(url:any, body:any)-
post(url:any, body:any, headers:any): post(url, body, {"x-api-key": key}): the map's pairs are the request's headers; an answer of status >= 400 is the error, with the answer's text
The standard library module collections (notes/stdlib.md): use collections, classes over a list field
class Stackclass Queueclass Dequeclass Setclass Counter-
OrderedMap(): warp maps keep insertion order: an ordered map is a map
The standard library module hash (notes/stdlib.md section 7): use hash, through the adapter std_pure, of a text's UTF-8 bytes: sha256 as lowercase hex, crc32 as a number
sha256(subject:any)crc32(subject:any)
The standard library module regex (notes/stdlib.md section 7): use regex, through the adapter std_pure: Rust's regex natively, JS RegExp in the browser, held to what both do alike (no look-around, no backreferences)
matches(subject:any, pattern:any)first_match(subject:any, pattern:any)find_all(subject:any, pattern:any)replace_all(subject:any, pattern:any, replacement:any)
The standard library module file (notes/stdlib.md section 7): use file, or a file URL in the program (P183). read, write, exists, write_bytes and read_bytes are prelude words (P171), the rest needs the module; append is written file.append(path, text). They call the adapter std_io: the file system natively, the page's in-memory files in the browser
write(path:any, text:any)-
write_bytes(path:any, bytes:any): a file's bytes as a list of ints 0 to 255 (a .wasm a warp-written emitter writes) read_bytes(path:any)append_file(path:any, text:any)exists(path:any)list_files(folder:any)lines(path)
The standard library module json (notes/stdlib.md section 7): use json. Warp data is a superset of JSON; the adapter std_pure parses and writes it (serde_json natively, JSON.parse / JSON.stringify in the browser); parse reads JSON5 too (comments, single quotes, trailing commas, bare keys), and json(t) is json.parse(t) without use json
parse_json(text:any)to_json(value:any)-
to_json_of_classes(value:any, classes:any): to_json in a program with classes (class_methods lower_json_classes): an instance is its fields
The standard library module os (notes/stdlib.md section 7): use os, through the adapter std_io; the browser has no environment (env gives ø) and no command line (args gives [])
env(name:any)-
args: the command line arguments after the program file:warp run prog.warp a bgives ["a" "b"] -
exec(command:any):exec sh "crontab -l": the command (a sh template, its argument vector) run without a shell, what it printed; natively only, the browser runs no processes
The standard library module list (notes/stdlib.md): standard functions of every program, unique(xs) or xs.unique(), no use needed (use list only for the qualified list.zip(a, b))
unique(xs)zip(a, b)enumerate(xs)product(xs)take(xs, n)drop(xs, n)flatten(xs)chunk(xs, n)window(xs, n)median(xs)flat_map(xs, f)-
partition(xs, f): [kept, rest]: the elements f holds for, and the others max_by(xs, f)min_by(xs, f)-
group_by(xs, f): {key: [elements]}: the elements by the text of f's value -
tally(xs): {element: how often} zip_with(a, b, f)sum_by(xs, f)count_by(xs, f)-
rotate(xs, n): the elements moved n places to the left interleave(a, b)-
dedupe(xs): without runs of equal neighbours -
scan(xs, start, f): the running results of f: scan([1, 2, 3], 0, (a, b) => a + b) is [1 3 6] take_while(xs, f)drop_while(xs, f)-
argmax(xs): the index (from 0, like xs[i]) of the greatest element, the first of equal ones argmin(xs)-
pairwise(xs): the neighbours: pairwise([1, 2, 3]) is 1 2] [2 3 -
split_at(xs, n): [the first n, the rest] -
cartesian(a, b): every pair of an element of a and one of b -
mode(xs): the most frequent element, the first of equally frequent ones -
variance(xs): the population variance and standard deviation stdev(xs)-
index_where(xs, f): the position (from 1, like index_of) of the first element f holds for, 0 when none does last_n(xs, n)-
fill(n, value): n copies of value: fill(3, 0) is [0 0 0] -
minmax(xs): [smallest, greatest] -
extend(xs, ys): Python's list methods (card python-stdlib): extend appends each of ys in place, index is the position from 0 -
concat(xs, ys): JavaScript's concat: a new list of xs then ys index(xs, x)
The standard library module math (notes/stdlib.md): use math, together with the C library libm
gcd(a, b)lcm(a, b)clamp(x, low, high)sign(x)-
round_to(x, digits): x rounded to the given number of decimal places: round_to(3.14159, 2) is 3.14 factorial(n)is_prime(n)-
lerp(a, b, t): the value a fraction t of the way from a to b is_even(n)is_odd(n)-
digits(n): the decimal digits of a whole number: digits(1234) is [1 2 3 4] -
choose(n, k): the number of ways to choose k of n (the binomial coefficient) -
mod_pow(base, exponent, modulus): base^exponent % modulus without the huge power -
percent(part, whole): part as a percentage of whole: percent(1, 4) is 25 to_radians(degrees)to_degrees(radians)-
isqrt(n): the whole square root, rounded down is_square(n)divisors(n)prime_factors(n)-
to_base(n, base): the digits of n in a base up to 36: to_base(255, 16) is "ff" -
bit_count(n): the one bits of whole numbers ≥ 0 (&and|are logical,xoris bitwise already): bit_count(6) is 2 -
bit_and(a, b): two's-complement bits of any whole numbers, by a + b = (a xor b) + 2 * bit_and(a, b): bit_and(-129, 127) is 127 bit_or(a, b)from_base(t, base)-
square(x): The C names still work afteruse math, each with a note naming the word here (modules STD_ALIASES) square_root(x)cube_root(x)power(base, exponent)exponential(x)natural_log(x)binary_log(x)decimal_log(x)-
logarithm(x, base): the logarithm of x to any base: logarithm(8, 2) is 3 sine(x)cosine(x)tangent(x)arc_sine(x)arc_cosine(x)arc_tangent(x)arcsinarccosarctan-
angle(x, y): the angle of the point (x, y) from the x axis, in radians: C's atan2(y, x) hyperbolic_sine(x)hyperbolic_cosine(x)hyperbolic_tangent(x)-
hypotenuse(a, b): the length of the long side of a right triangle with sides a and b ceiling(x)-
whole_part(x): x without its fraction, toward zero: whole_part(-2.5) is -2 -
remainder(a, b): what remains of a after taking out b as often as it fits, with the sign of a (C's fmod)
The standard library module text (notes/stdlib.md): standard functions of every program, repeat(t, 2) or t.repeat(2), no use needed (use text only for the qualified text.repeat(t, 2))
repeat(t, n)pad_left(t, width)pad_right(t, width)-
format(template, values): format("{} has {} items", ["cart", 3]): each {} takes the next value -
words(t): the words between runs of spaces lines(t)capitalize(t)center(t, width)title(t)-
slug(t): lower case letters and digits, the rest as single dashes: "Hello, World!" → "hello-world" truncate(t, width)-
is_blank(t): only spaces, tabs and line breaks, or nothing -
is_upper(t): has letters, all upper (or lower) case is_lower(t)remove_prefix(t, prefix)remove_suffix(t, suffix)-
count_of(t, part): how often part occurs, not overlapping: count_of("banana", "an") is 2 is_palindrome(t)word_count(t)-
snake_case(t): "helloWorld", "Hello World", "hello-world" → "hello_world" kebab_case(t)-
camel_case(t): "hello_world" → "helloWorld" -
indent(t, n): each line indented by n spaces -
is_numeric(t): a whole or decimal number, optionally signed: "12.5", "-3" -
between(t, opening, closing): the text between the first opening and the next closing after it, "" when either is missing -
wrap(t, width): the words in lines of at most width characters -
class Cursor: a reading position in a text, for scanners and parsers:c = Cursor("ab12"); c.take_while(is_letter)is "ab", thenc.peek()is '1';atcounts the characters read (an index)
The standard library module random (notes/stdlib.md): use random, over the host words random and random_below
choice(xs)shuffle(xs)sample(xs, k)-
seed(n): the same numbers after the same seed: seed(42); [random_below(100), random()]
The standard library module map (notes/stdlib.md): standard functions of every program, merge(a, b) or a.merge(b), no use needed (use map only for the qualified map.merge(a, b))
merge(a, b)map_values(m, f)-
invert(m): {a:1 b:2} → {1:"a" 2:"b"}: the values become the keys -
pick(m, wanted): only the entries of the given keys that m has -
from_pairs(pairs): "a", 1] ["b", 2 → {a:1 b:2} -
omit(m, unwanted): the entries of m without the given keys -
filter_values(m, f): the entries whose value f holds for -
entries(m): {a:1 b:2} → "a", 1] ["b", 2, the opposite of from_pairs -
get_or(m, key, fallback): the value of key, or fallback when m has none -
find_key(m, f): the first key whose value f holds for, ø when none -
update(m, other): Python's dict methods (card python-stdlib): update merges in place, items are the entries, setdefault keeps the default for a missing key and gives the key's value items(m)setdefault(m, key, fallback)-
popitem(m): the last entry as [key value], removed from m in place (Python's dict.popitem)
The standard library module time (notes/stdlib.md): use time, the calendar over clock() (milliseconds since 1970, UTC)
day_number(ms)-
date_of(ms): Howard Hinnant's civil_from_days: the proleptic Gregorian date of a day number -
weekday(ms): ISO weekday: Monday 1 … Sunday 7 today()add_days(ms, n)days_between(from, to)two_digits(n)-
format_date(ms): ISO 8601: 2026-10-07 -
format_time(ms): the time of day, UTC: 13:05:09 -
days_from_date(year, month, day): Howard Hinnant's days_from_civil: the day number of a proleptic Gregorian date -
parse_date(t): "2026-10-07" → milliseconds since 1970 at midnight UTC -
format_duration(ms): milliseconds as the largest units: 5430000 → "1h 30m 30s", 250 → "250ms" is_leap_year(year)days_in_month(year, month)
The standard library matrix module (notes/stdlib.md): use matrix. A matrix is a list of rows: m[i][j] (m#i#j) reads and writes an element, printing and equality are those of lists. Locals are var: a program's own m or row stays apart from them
matrix(r, c, f)filled_matrix(r, c, v)zeros(r, c)ones(r, c)random_matrix(r, c)identity(n)rows(m)cols(m)shape(m)transpose(m)matrix_add(a, b)scale(m, k)map_matrix(m, f)dot(u, v)matmul(a, b)
The standard library module draw (notes/stdlib.md, card drawing-words): use draw, a canvas of colored pixels shown by paint (the playground's canvas, natively a PNG). A color is a number 0xAARRGGBB: rgb, hsv, the named colors, with_alpha
-
paper: paper: the canvas before anything is drawn, as paint shows 0 (src/graphics/paint.rs PAPER) blackwhitegrayredgreenblueyelloworangepurple-
cell(v): the pixel a coordinate falls in -
rgb(r, g, b): r, g, b from 0 to 255 -
with_alpha(color, alpha): alpha from 0 (invisible) to 1 (opaque) alpha_of(color)-
clear_shape: what draw_shape's kind says (src/graphics/gpu_canvas.rs) rect_shapecircle_shape-
pixels_for(width, height): the pixels the canvas keeps here: none when they are on the GPU -
channel_mix(color, under, a, place): one channel (its place 65536, 256 or 1) of color over under, by alpha a from 0 to 255
The standard library module markup (card web-ssr, notes/web_framework.md "Built sites"): use markup (not html, which samples/web/html.warp would shadow). to_html(value) is the HTML of a markup value, div{ class:"box" h1{"Hi"} } →
style: { fontSize: 12 } inline CSS), anything else a child in order.
html_elements-
html_raw_text_elements: elements whose content is their own language as written (JavaScript, CSS), not escaped text -
html_void_elements: elements without content or closing tag html_attributes-
html_boolean_attributes: attributes that are present or absent:checked: done -
html_meta_attributes: a meta element's own attributes:meta{ charset: "utf-8" }stays the element,meta: { author: "Ann" }names metas html_unitless_propertiesto_html(value:any)-
html_render(value:any, scope:any, chosen:any):scope: the component whose elements a style sheet styles (data-warp-scope, card web-scoped);chosen: the value of the select around, whose option is selected (select{ bind: fruit }, card web-bind-select) html_is_element(value:any)html_element(tag:any, content:any, scope:any, chosen:any)-
html_is_page_fact(item:any):html{ title: "Shop" description: "…" meta: { author: "Ann" } }: facts about the page, for its head (card html-meta) html_page_fact(name:any, value:any)-
html_names_any(value:any, names:any): does a block of pairs name any ofnames -
html_items(content:any): the items of an element's block, or its one item; a line of pairs (form{ method:"post" action:"/t"before more lines) is its pairs, attributes among them -
html_is_group(value:any): a block{…}or a list[…]: at run time a block is a map, no list (card inside-function) -
html_is_attribute(item:any, tag:any):class:"box"inside an element: an attribute when its name is one and its value plain (or inline CSS for style) -
html_holds_pairs(value:any):class:["btn" "btn-info"]is an attribute,style{ ".card": {…} }an element: its items are rules html_attribute(item:any)-
html_attribute_name(name:any):li{ key: todo.id … }names a list item: the attribute data-warp-key, by which the page moves its element -
html_is_declarations(value:any):{ color: theme padding: 8 }: a block of CSS properties with plain values -
html_css(value:any):color: red; padding: 8px: camelCase names in kebab-case, numbers in pixels unless the property has no unit html_declaration(item:any)-
html_css_value(property:any, value:any): a number in pixels unless the property has no unit -
html_style_rule(rule:any, scope:any):style{ ".card": { padding: 8 } }: a ruleselector { declarations }; a text is CSS as written -
html_scoped(selectors:any, scope:any):h2, pin the component Card:[data-warp-scope="Card"] h2, [data-warp-scope="Card"] p -
html_kebab(name:any): CSS names are ASCII: lowered by hand, so a page carries no Unicode case table (card web-bundle-growth) -
html_attribute_value(value:any):class:['btn' 'btn-info']is the attributebtn btn-info -
html_plain(value:any): a value as the text it shows: a text without quotes, anything else as warp writes it html_is_true(value:any)html_escaped(text:any)-
html_tag(name:any):js{…}is the element script -
html_element_at(value:any, path:any): The playground reads a component's holes from the page's rendering (card web-fine-components, lowering/component_state.rs): the element atpath, its element indices from the root down as the page'schildrencount them, and the text afterafterof its child elements html_text_at(value:any, path:any, after:any)html_child_elements(element:any)-
html_child_items(element:any): an element's items that are no attributes -
html_elements_in(item:any): the elements an item shows: itself, or those of a group
The standard library module router (card web-router, notes/web_framework.md "Routes"): a route pattern "/users/:id" matches the path "/users/7" with the parameter id = 7; "" matches any path (the not-found page). A parameter may declare its type (card route-typed): ":id:int" matches digits only, ":price:float" a decimal number, ":name:text" any part, given as text even when it is digits. The browser's URLPattern syntax too (card route-urlpattern): the last part may be optional (":tab?", ø when absent) or take the rest of the path (":path" zero or more parts, ":path+" one or more, joined by "/"; "*" unnamed); lowering/routes.rs checks a parameter's regular expression (":id(\d+)"), which matches any part here. lowering/routes.rs makes each route "…" {…} of a page a function and picks the first one matching page_path().
route_segments(path:any)route_matches(pattern:any, path:any)-
route_segment(pattern:any, path:any, name:any): the part of the path the parameter:nameof the pattern stands for, as text; ø when the pattern has none -
route_parameter(pattern:any, path:any, name:any): the parameter:namewithout a declared type: a number when it is digits ("/users/7" gives id 7), else its text (lowering/routes.rs converts a typed one itself) -
route_part_name(part:any): the name of the parameter a pattern part declares (":id:int", ":id(\d+)", ":id?" → "id"), "" for a fixed part -
route_part_type(part:any): the type a parameter declares (":id:int" → "int"), "" when it declares none (nor with a URLPattern mark or group) -
route_part_mark(part:any): how often the last part of a pattern may come (URLPattern): "?" at most once, "*" any number, "+" at least once, "" exactly once -
route_number(segment:any, dots:any): whether a path part is all digits, with at mostdotsdecimal points among them -
route_fits(kind:any, segment:any): whether a path part fits the declared type of its parameter
The standard library module wagi (card fermyon-hosting, notes/hosting.md "Fermyon"): warp build --wagi makes a program's routes answer one request the WAGI way (Spin's wagi executor, Akamai Functions): the request comes in the environment (REQUEST_METHOD, PATH_INFO, QUERY_STRING), the answer goes CGI-style to stdout: headers, a blank line, the body. A text answers as text, anything else as JSON, as warp serve answers (src/web/web_server.rs Answer::of). A route's status 418 and header "name" "value" (card wagi-build, lowering/serve.rs with_answer_headers) are wagi_header calls: the answer carries them. Not yet: request bodies (stdin), percent-decoded query values.
wagi_header(name:any, value:any)wagi_variable(name:any)wagi_query(query:any)wagi_request()wagi_json_text(t:any)-
wagi_holds_pairs(value:any): a map ({n: 1, k: 2}in a route) is a list of pairs; ["a", "b"] holds none wagi_json_fields(value:any)wagi_json(value:any)wagi_reply(status:any, content_type:any, body:any)-
wagi_answer(value:any): the route's value with the status and headers it set -
wagi_failed(message:any): lowering/serve.rs page·submitted throws "no route answers …" for a request no route takes
The standard library module i18n (card web-i18n, notes/i18n.md): use i18n. Translations are data, one map per language; a message is a text with {name} holes, or a map of plural categories (Unicode CLDR: zero one two few many other) chosen by the value count: messages = { en: { cart: { one: "{count} item", other: "{count} items" } }, de: { cart: { one: "{count} Artikel", other: "{count} Artikel" } } } translate(messages, "de", "cart", { count: 3 }) → "3 Artikel" A language the messages lack, or a message one language lacks, comes from the first language (de-AT reads de first).
translate(messages:any, language:text, key:text, values:any)-
i18n_message(messages:any, language:text, key:text): The message of a key: in the language, its base language (de for de-AT), else the first language -
i18n_plural_form(forms:any, category:text): A plural message's form for the category, else its form other -
i18n_filled(message:text, values:any): The text with each {name} replaced by the value named name -
plural_category(language:text, n:int): The CLDR plural category of a whole number in a language: "one", "few", "other", …
The standard library units module (card units-dynamic, notes/units_runtime.md): quantities whose unit is known only at run time, quantity("5 km") read from text or quantity(5, unit) of a unit named by data. A quantity carries its unit as data: the amount in SI base units (exact where the text is), its dimension and the unit it shows in. Units written in the program stay static (src/units): checked at compile time, plain numbers at run time.
-
unit_names: The units by name, their SI amount and dimension: the dimension packs the powers of length, mass and time as length + 256·mass + 65536·time, so multiplying quantities adds dimensions unit_scalesunit_dimensionsclass Quantity-
same_dimension(q:Quantity, o:any, action): o when it measures what q measures, else the loud DimensionError -
bound_of(x, bound): the bound of an amount with tolerance by name (inside Quantity,amount.lowwould call its method low) -
quantity_text(q:Quantity): "5km": the amount in its own unit (str(q) of a parameter q:Quantity misses the text witness, card param-text-witness); a Gaussian amount keeps its σ apart from the unit, "12.00 ± 0.60σ m" -
unit_product(first, second):m·mism² -
unit_factor(u): one unit by name, a power of one (m²,s^2) or a product of them (m·kg,kg*m): [its SI amount, its dimension] -
unit_measure(u): a unit as written,km/horm/s²: [its SI amount, its dimension] -
quantity(amount, u):quantity(5, "km"): amount of the unit u;quantity("5 km"),quantity("2.5km/h"): read from text quantity(t:text)-
exact_decimal(t:text): "-2.5" as the exact -5/2 (as numberwould read a float)
The standard library module agent (card g_X_F0): agent "summarize this text" sends the prompt as given to Claude (the Anthropic Messages API) and gives its answer as text; agent(prompt, "claude-opus-5-5") names another model; with an expected type (x:int = agent "33/3", agent "…" as bool) it answers a value of that type (agent_as). The key is ANTHROPIC_API_KEY: natively the environment's (a terminal's export ANTHROPIC_API_KEY=sk-ant-…, in ~/.zshrc to keep it), in the browser the API key field of the playground's ⋯ menu (kept in that browser only). Loaded when a program calls agent, like units
agent(prompt:text)agent(prompt:text, model:text)-
agent_as(prompt:text, type:text): card int-let: a call with an expected type calls this companion (lowering/overloads.rs):x:int = agent "33/3"asks for a value of that type written as JSON and gives it as that value; text asks as agent does
The standard library module sound (card basic-sound): play(440Hz, 0.5s), play(C4), play([C4 E4 G4]) (a chord, as in Sonic Pi), play(note("C#4")), melody([C4 E4 G4]) (one note after another), beep, tone(frequency, seconds, "square"). Frequencies and durations are numbers or quantities (440Hz, 0.5s, 250ms), read by si_amount as plain numbers (src/units/static_units.rs). The samples are made here and played by the host word sound_samples: natively a WAV file in the temporary folder (warp-sound/sound.wav), played only when warp may reach the user, and in the browser WebAudio. Loaded when a program calls one of its words (src/modules.rs SOUND_WORDS)
beat_seconds(beats)bar_seconds(bars)-
sample_offset: the samples cross to the host as whole numbers ≥ 0: amplitude + 32768 (src/sound/mod.rs SAMPLE_OFFSET), a stereo sound's interleaved left, right loudest_sample-
scale_letters: a note letter's semitone above C is its place here, from 0 -
midi_hertz(n): the frequency of MIDI note n (C4 is 60) at the tuning, equal-tempered, to a hundredth of a Hz as tables write it (C4 = 261.63): a note name lowers to it (src/lowering/music_words.rs) -
midi(pitch): the MIDI note nearest a frequency: midi(C4) is 60, midi(440Hz) 69 -
note_names: the name of the note nearest a frequency, with sharps: note_name(Eb4) is "D#4" note_name(pitch)-
note(name): the frequency of a note name: note("A4") is 440, note("C#4") a semitone above C4, note("Eb5") one below E5 -
transpose(pitch, semitones): a pitch (or list of them) semitones higher, lower when negative: a note stays that note (transpose(C4, 12) == C5), any other frequency is multiplied (transpose(300Hz, 12) is 600) transposed(frequency, semitones)-
chord_intervals: the semitones of a chord's notes above its root, and of a scale's up to its octave: chord(C4, major7), scale(D4, dorian) (a kind word the program doesn't define is its text, src/lowering/music_words.rs) scale_intervalschord(root, kind)scale(root, kind)transpose_each(root, intervals)-
decibels(level): the gain factor of decibels: loudness = -6 dB is about half (src/lowering/music_words.rs reads-6 dB) -
wave(shape, p, dt = 0.0): one wave at phase p (0 to 1) of its period, from -1 to 1, a sample advancing the phase by dt; the jumps of square and sawtooth are band-limited (card reason-beep), sharp without dt -
step_smoothing(p, dt): the correction of a wave's upward jump of 2 at phase 0 within a sample of it (PolyBLEP): a sharp jump has harmonics above half the sample rate, which fold back as an inharmonic buzz (880 Hz beep at 22050 samples a second) -
sample_time(i): the seconds at sample i: a float source (decision exact-decimals), so the samples' math runs in f64, not in ratios -
ramp(steps, seconds): how far a ramp of seconds has come after steps samples: 0 to 1 -
envelope(i, n): the level of sample i of n (ADSR): 0 at both ends -
phase(f, i): the cycles a wave of frequency f has run at sample i, its vibrato included: the integral of f · (1 + c·sin(2π r t)) -
tremolo_gain(i): the gain of the tremolo at sample i: 1 at the start, 1 - tremolo at its lowest voices_of(pitches)-
chord_samples(pitches, duration, shape): the samples of frequencies sounding together -
echo_floor: below this share of the level the echoes and the room's tail are cut off max_echoesreverb_seconds-
reverb_delays: the delays (seconds) and the feedback of the four parallel combs of the reverb (Schroeder) reverb_feedbackeffects_on()-
echoes_of(feedback): the number of repeats until a feedback has died below echo_floor dry_at(amplitudes, i)-
panned(samples): the samples for the speakers: mono in the middle, else interleaved left, right, the far side quieter by the pan sound(samples)-
tone(pitch, duration, shape): one wave shape: tone(440Hz, 0.5s) (a sine), tone(220Hz, 100ms, "square") beep()-
pitches_of(x): a frequency, or a list of them sounding together (a chord) -
play_file(path): a music file in the background (wav, mp3, ogg, flac, aiff, m4a): play "song.mp3"; stop_sound stops it -
stop_sound(handle = 0): play gives the sound's handle: h = play(C4, 2s); stop_sound(h) stops that one alone, stop_sound (handle 0) all -
fade_sound(handle, gain, seconds = 0.05): a playing sound's gain ramps to gain (1 as played, 0 silent) over the seconds, sample by sample: h = play(C4, 4s); fade_sound(h, 0, 2) fades it out over 2 seconds; handle 0 fades all. render_sound writes the fade too -
play_signal(signal, seconds): a signal computed while it plays (card real-time): hum(t) := 0.3 * sin(2 * pi * 220 * t); play(hum, 2s) (or play_signal(hum, 2s); play([left, right], 2s) in stereo) calls hum for every sample, t its time in seconds, a block ahead of the speaker; returns the handle when the last is queued -
sound_queued(): play returns at once, its sound queued behind those before it: sound_queued() is how many seconds its voice still sounds, wait_sound waits for them (a program's end does too) wait_sound()-
render_sound(path): the sounds since the last render (or the start) one after another in one WAV file, offline (also without speakers): render_sound("song.wav") gives its seconds -
sound_at(seconds):at 2 beats play C4,at 1 bar { … }(card sample-accurate): the statement's sounds start that many seconds after the voice's first sound, exactly so in render_sound; the voice goes on where it stood (src/lowering/music_words.rs) sound_at_end()-
melody_samples(notes, seconds): one note (or chord) after another: melody([C4 E4 G4]), melody([C4 E4 G4], 250ms). Plain seconds: the unit check reads a quantity parameter in a loop as unsupported (notes/units_runtime.md) -
pattern_note(word): a pattern item is [0, items] (a group) or [1, frequencies] (a sound, no frequencies: a rest) -
pattern_euclid(item, k, n): k notes over n steps as evenly as possible: step i sounds when (i * k) mod n < k pattern_end(text: text, from: int, stops: text)silence(n)-
midi_send(status, data1, data2 = 0, port = ""): MIDI (card midi-out): midi_on C4, midi_off C4, midi_send(144, 60, 100) to the first output device (or the browser's Web MIDI output), midi_outputs() their names; channels count from 1, velocity 1 to 127 midi_on(pitch, velocity = 100, channel = 1)midi_off(pitch, channel = 1)midi_outputs()-
midi_receive(): the next message [status, data1, data2] waiting at the input, ø when none (fails where there is no MIDI input) -
write_midi(path, notes): a Standard MIDI File of notes [start, pitch, length, velocity] (seconds, frequency or note, seconds, 1 to 127) at 120 beats a minute, and the notes of such a file the same way: write_midi("tune.mid", 0, C4, 0.5, 100) read_midi(path)-
spectrum_window: the samples a spectrum looks at: 512 at 22050 Hz are 23 ms, bands 43 Hz apart are still told apart -
band_frequency(i, count): the middle frequency of band i of count -
nearest_band(frequency, count): the band whose middle frequency is nearest in pitch