Template - Markdown#
This page is a living template for MyST Markdown pages (.md). It
demonstrates every feature available when authoring a prose-only chapter —
formatting, math, admonitions, exercises, figures, cross-references, and
tables — but excludes notebook-only features (executable code cells, glue,
and cell tags). For those, see the notebook template.
Use it two ways:
As a reference — skim the rendered page to see what is available.
As a starting point — copy
template.md, rename it, and replace the content with your own.
1. Markdown pages vs. notebooks#
Every page in this book is one of two file types:
.md— a MyST Markdown file (this page)Prose, math, and directives. Best for chapters that are mostly explanation. Code blocks are displayed but not executed.
.ipynb— a Jupyter notebookMarkdown cells and code cells. Code runs when the book is built, and its output — numbers, plots, audio players — is captured into the page. Best for anything that should demonstrate running code.
Markdown cells inside a notebook understand the same MyST syntax as a .md
file, so a notebook is a strict superset: everything in this template also
works inside a notebook.
Important
If your page needs to execute Pyquist code, author it as a notebook instead. See the notebook template for the full set of notebook-only features.
2. Text formatting#
Every page pairs the Source (what you type) with the Rendered result.
Source:
**Bold**, *italic*, ***bold italic***, `inline code`, <del>strikethrough</del>,
H<sub>2</sub>O, x<sup>2</sup>, and a [hyperlink](https://pyquist.org). Press
{kbd}`Shift` + {kbd}`Enter` to run a cell. The {abbr}`DFT (Discrete Fourier Transform)`
abbreviation shows its meaning on hover.
> A blockquote — use it for short asides or quotations.
A horizontal rule follows:
---
Inline math such as $f = 440\,\text{Hz}$ flows inside running text.
Rendered:
Bold, italic, bold italic, inline code, strikethrough,
H2O, x2, and a hyperlink. Press
Shift + Enter to run a cell. The DFT
abbreviation shows its meaning on hover.
A blockquote — use it for short asides or quotations.
A horizontal rule follows:
Inline math such as \(f = 440\,\text{Hz}\) flows inside running text.
3. Lists#
Unordered, ordered, and nested.
Source:
- First item
- Second item
- Nested item
- Another nested item
- Third item
1. Step one
2. Step two
3. Step three
Rendered:
First item
Second item
Nested item
Another nested item
Third item
Step one
Step two
Step three
A task list (the tasklist extension).
Source:
- [x] Install Pyquist
- [x] Write the template
- [ ] Write Chapter 1
Rendered:
Install Pyquist
Write the template
Write Chapter 1
A definition list (the deflist extension).
Source:
Sample rate
: The number of audio samples stored per second, in hertz.
Nyquist frequency
: Half the sample rate; the highest representable frequency.
Rendered:
- Sample rate
The number of audio samples stored per second, in hertz.
- Nyquist frequency
Half the sample rate; the highest representable frequency.
4. Admonitions#
Admonitions are colored callout boxes. Swap note for tip, important,
warning, seealso, or admonition (with a custom title).
Source:
:::{note}
A **note** — neutral, supporting information.
:::
:::{tip}
A **tip** — practical advice.
:::
:::{important}
**Important** — do not miss this.
:::
:::{warning}
A **warning** — something that can go wrong.
:::
:::{seealso}
A **see-also** — a pointer to related material, e.g. the
{doc}`Pyquist reference <../pyquist/Overview>`.
:::
:::{admonition} Custom title
:class: hint
The generic `{admonition}` directive takes a custom title and any color class.
:::
Rendered:
Note
A note — neutral, supporting information.
Tip
A tip — practical advice.
Important
Important — do not miss this.
Warning
A warning — something that can go wrong.
See also
A see-also — a pointer to related material, e.g. the Pyquist reference.
Custom title
The generic {admonition} directive takes a custom title and any color class.
A collapsible admonition (:class: dropdown).
Source:
:::{admonition} Click to expand
:class: dropdown note
Hidden until the reader clicks.
:::
Rendered:
Click to expand
Hidden until the reader clicks.
5. Audio#
MyST has no native audio directive, so the book adds one: the custom {audio}
directive for a single clip (defined in _ext/icm_audio.py), plus a multimodal
grid convention for pairing audio with images.
5.1 Audio clips — the {audio} directive#
For short audio clips shipped alongside a chapter (a recorded sample, a pre-rendered WAV), use the {audio} directive. Its body is a Markdown link to the clip — the link text describes it — followed by an optional caption. The directive renders a clean audio-block card: a large round play/pause button (the same control as the inline {audio} role) beside the caption, on a subtle tinted panel. The link text becomes the button’s aria-label/tooltip. This is a book-specific directive — see directives.md, defined in _ext/icm_audio.py (behavior wired by _static/audio-chip.js). Its body matches the upstream icm-text source verbatim; only the fence marker differs (:::audio there, :::{audio} here).
Source:
:::{audio}
[A 440 Hz sine tone](../book/ch01/assets/audio-sine-440.wav)
A 440 Hz sine tone, one second long, at $f_s = 44{,}100$ Hz.
:::
Rendered:
For audio generated at build time by executable Pyquist code, use a notebook
page with pq.play(audio) — see the notebook template.
5.2 Inline audio and audio grids#
For a clip inline — mid-sentence, or paired with a waveform image — use the
{audio} role (the inline counterpart of the {audio} directive above):
{audio}`label <url>`. It renders a small round play/pause button
(wired by _static/audio-chip.js) followed by the label — so the clip is
self-contained, no separate text needed. $…$ in the label renders as math.
To compare several clips under one shared caption, group them: one paragraph
per item, then a final paragraph as the shared caption. Three wrappers
(styled in _static/custom.css):
audio-figure— each clip paired with its own waveform image; narrow grid columns for a side-by-side comparison.audio-board— several clips above one combined plot (the image is its own paragraph); the buttons flow in a centered row, the plot spans full-width below.audio-list— clips with text labels only; wider columns so each label sits on one line.
(For the upstream :::figure source the split tool picks the wrapper
automatically: audio-figure if every clip has its own image, audio-board if
the clips share a standalone image, else audio-list.) Source:
:::{audio-figure}
{audio}`Clean 440 Hz sine <../book/ch01/assets/audio-sine-440.wav>` 
{audio}`Clipped 440 Hz sine <../book/ch01/assets/audio-clipped-sine.wav>` 
A clean 440 Hz sine (left) and the same tone clipped (right) — play each, then compare its waveform.
:::
Rendered:
A clean 440 Hz sine (left) and the same tone clipped (right) — play each, then compare its waveform.
A text-only list of examples uses audio-list instead:
:::{audio-list}
{audio}`A clean 440 Hz sine <../book/ch01/assets/audio-sine-440.wav>`
{audio}`The same tone, hard-clipped <../book/ch01/assets/audio-clipped-sine.wav>`
Two tones to compare by ear.
:::
Rendered:
In the upstream icm-text source these are authored as :audio[label](url),
:figure, and a :::figure wrapper; the split tool folds each
clip’s [label] into the {audio} role (dropping any descriptive text beside
it) and picks the audio-figure / audio-board / audio-list wrapper shown
here.
5.3 Student showcase — the {showcase} directive#
The course Showcase page features one card per piece with the {showcase} directive (defined in _ext/icm_showcase.py; it shares the play button and download control with {audio}, and _static/audio-chip.js drives its seek bar). The body is a Markdown link whose text is the student’s name and whose target is the clip, followed by the composer’s notes as ordinary Markdown. The card shows the name, a seek bar with a time readout, and the notes under a “Composer’s notes” label (a card with no notes has no label). Write the name as Anonymous for an unattributed piece — the card styles it as such. Names are plain text (no bold or links inside the brackets), and a directive nested in the notes needs the outer fence lengthened to ::::{showcase}. On the course site the clips sit beside the page in a per-assignment folder (showcase/A1/), which the Makefile copies into the build.
Source:
:::{showcase}
[Ada Lovelace](../book/ch01/assets/audio-sine-440.wav)
A few sentences from the composer: what the piece is, how it was made, and what to listen for.
:::
Rendered:
6. Mathematics#
Inline and display math.
Source:
Inline math: the angular frequency is $\omega = 2\pi f$.
Display math:
$$
x(t) = A \sin(2\pi f t + \phi)
$$
Rendered:
Inline math: the angular frequency is \(\omega = 2\pi f\).
Display math:
A labeled, numbered equation, referenced inline with {eq}`eq-euler-md`.
Source:
:::{math}
:label: eq-euler-md
e^{i\pi} + 1 = 0
:::
…see equation {eq}`eq-euler-md`.
Rendered:
…see equation (1).
Aligned, multi-line math.
Source:
$$
\begin{aligned}
X[k] &= \sum_{n=0}^{N-1} x[n]\, e^{-i 2\pi k n / N} \\
&= \sum_{n=0}^{N-1} x[n]\,\big(\cos\theta - i\sin\theta\big)
\end{aligned}
$$
Rendered:
Colored terms, using the macros defined in _config.yml:
$\blue{a} + \red{b} = \green{c}$ → \(\blue{a} + \red{b} = \green{c}\).
7. Code blocks (not executed)#
A plain fenced block is shown with syntax highlighting but not run:
# Illustration only — this block does not execute.
import pyquist as pq
audio = pq.Audio(samples, sample_rate=44100)
The {code-block} directive adds line numbers and line emphasis:
1def gain(audio, factor):
2 audio.samples *= factor # the emphasized line
3 return audio
Important
In a .md file, code blocks are always display-only. To run code at build
time, author the page as a notebook instead.
7.1 Embedding a live notebook — the {interactive} directive#
There is one exception to “code in a .md is display-only.” The book-specific
{interactive} directive embeds a companion notebook from the chapter’s
notebooks/ folder as live cells the reader can read, edit, and run in the
browser. Author it as a single line — the notebook path in [brackets]:
:::{interactive}[notebooks/my-widget.ipynb]
:::
When the split pipeline sees this directive, it emits that whole section as a
Jupyter notebook instead of Markdown: the prose becomes Markdown cells and
the companion notebook’s cells are spliced in where the directive was —
executed at build time (so their output is baked into the page) and wired to
the live-code runtime. Each code cell chooses its visibility with a whole-line
# hide / # collapse / # show marker. The rest of the book is unchanged —
only sections that use {interactive} become notebooks, and a section may
embed more than one.
See the interactive template for the full tutorial: the widget house style, the libraries a widget may use, and the visibility markers, around a working demo.
8. Figures and images#
For most figures you only need an image and a caption — write the image as the
first line of a {figure} block (no options, no path argument). Source:
:::{figure}

A sine waveform — a static image stored in `content/templates/images/`.
:::
renders as:
Fig. 77 A sine waveform — a static image stored in content/templates/images/.#
When you need to size, align, or cross-reference a figure, use the standard
form instead: pass the path as the directive argument and add options. :name:
makes it referenceable with {numref}. Source:
:::{figure} images/template-waveform.png
:name: fig-waveform-md
:width: 80%
:align: center
A sine waveform, sized and named.
:::
See {numref}`fig-waveform-md` for an auto-numbered link.
renders as:
Fig. 78 A sine waveform, sized and named.#
See Fig. 78 for an auto-numbered link.
9. Tables#
A plain Markdown table.
Source:
| Waveform | Harmonic content |
| -------- | ---------------- |
| Sine | Fundamental only |
| Square | Odd harmonics |
| Sawtooth | All harmonics |
Rendered:
Waveform |
Harmonic content |
|---|---|
Sine |
Fundamental only |
Square |
Odd harmonics |
Sawtooth |
All harmonics |
A headerless table: write body rows only, no |---| line. (A table whose
header cells are all empty renders the same way.)
Source:
| **Sine** | Fundamental only |
| **Square** | Odd harmonics |
| **Sawtooth** | All harmonics |
Rendered:
Sine |
Fundamental only |
Square |
Odd harmonics |
Sawtooth |
All harmonics |
The {list-table} directive (easier for long cell text; supports a caption and
label).
Source:
:::{list-table} Synthesis methods
:header-rows: 1
:name: tbl-methods-md
* - Method
- Idea
* - Additive
- Sum sinusoids
* - Subtractive
- Filter a harmonically rich source
:::
Rendered:
Method |
Idea |
|---|---|
Additive |
Sum sinusoids |
Subtractive |
Filter a harmonically rich source |
The {csv-table} directive.
Source:
:::{csv-table} Common sample rates
:header-rows: 1
Use, Rate (Hz)
Telephone, 8000
CD audio, 44100
Studio, 48000
:::
Rendered:
Use |
Rate (Hz) |
|---|---|
Telephone |
8000 |
CD audio |
44100 |
Studio |
48000 |
10. Cross-references and citations#
Target |
Role |
Live example |
|---|---|---|
A labeled section |
|
|
A numbered figure |
|
|
Another page |
|
|
An equation |
|
|
A theorem |
|
Citations pull from content/book/references.bib. Cite with
{cite}`dannenberg1997machine` → []. Every
citation is collected automatically on the References page.
11. Footnotes#
Footnotes attach a small reference that collects at the foot of the page.
Source:
Footnotes attach a small reference[^demo] that collects at the foot of the page.
[^demo]: This is the footnote text. Footnotes suit asides and source notes.
Rendered:
Footnotes attach a small reference[1] that collects at the foot of the page.
12. Margin content#
The {margin} directive (from sphinx-book-theme) pushes a block into the
right margin, aligned with the paragraph it follows. Use it for short asides,
side figures, or callouts that shouldn’t break the flow of the main text.
Important
Because margin blocks float out of the normal flow, they appear beside the paragraph that immediately follows them, not below a “Rendered:” label. The example below has a dedicated anchor paragraph so the margin content lines up correctly.
Source:
:::{margin} An aside
The {{ pyquist }} library is named after Harry Nyquist (1889–1976), whose
sampling theorem underpins all of digital audio.
:::
Rendered → look to the right of *this* paragraph. The margin block sits next
to the paragraph that follows its source. Keep the anchor paragraph at least
as tall as the margin content so the next section isn't displaced.
Rendered → look to the right of this paragraph. The margin block sits next to the paragraph that follows its source. Keep the anchor paragraph at least as tall as the margin content so the next section isn’t displaced.
You can also push a {figure} to the margin by adding :class: margin — handy
for side illustrations that comment on the body text without interrupting it.
13. Exercises and solutions#
The sphinx-exercise extension provides {exercise} and {solution}. Source:
:::{exercise}
:label: ex-demo-md
State the Nyquist frequency for a 48 kHz sample rate.
:::
:::{solution} ex-demo-md
:class: dropdown
24 kHz — half the sample rate.
:::
renders as:
Exercise 64
State the Nyquist frequency for a 48 kHz sample rate.
Solution to Exercise 64
24 kHz — half the sample rate.
An unlabeled {solution} goes inside the exercise it answers, and renders
as a “Reveal solution” button that keeps the answer hidden until the reader
clicks it. The outer fence grows to :::: so the nested ::: closes inside
it:
::::{exercise}
Which harmonics are present in a 440 Hz square wave, and how do their
amplitudes fall off?
:::{solution}
Odd harmonics only — 440 Hz, 1320 Hz, 2200 Hz, … — with the $k$-th harmonic
falling off as $1/k$.
:::
::::
renders as:
Exercise 65
Which harmonics are present in a 440 Hz square wave, and how do their amplitudes fall off?
Reveal solution
Odd harmonics only — 440 Hz, 1320 Hz, 2200 Hz, … — with the \(k\)-th harmonic falling off as \(1/k\).
A gated exercise ({exercise-start} … {exercise-end}) can wrap several
blocks:
Exercise 66
Describe the spectrum of a 330 Hz sawtooth wave. Which harmonics are present, and how do their amplitudes fall off?
14. Theorems, proofs, and definitions#
The sphinx-proof extension provides {prf:theorem}, {prf:proof},
{prf:definition}, {prf:lemma}, {prf:example}, and {prf:algorithm}.
Source:
:::{prf:definition} Sample rate
:label: def-sample-rate-md
The **sample rate** is the number of samples stored per second of audio.
:::
:::{prf:theorem} Nyquist–Shannon sampling theorem
:label: thm-nyquist-md
A signal containing no frequencies above $f_\text{max}$ is fully determined by
samples taken at a rate $f_s > 2\,f_\text{max}$.
:::
:::{prf:proof}
A full proof is omitted in this template; see any signal-processing text.
:::
:::{prf:example}
At $f_s = 44100$ Hz, frequencies up to $22050$ Hz can be represented.
:::
Rendered:
Definition 31 (Sample rate)
The sample rate is the number of samples stored per second of audio.
Theorem 4 (Nyquist–Shannon sampling theorem)
A signal containing no frequencies above \(f_\text{max}\) is fully determined by samples taken at a rate \(f_s > 2\,f_\text{max}\).
Proof. A full proof is omitted in this template; see any signal-processing text.
Example 2
At \(f_s = 44100\) Hz, frequencies up to \(22050\) Hz can be represented.
16. Substitutions#
Substitutions are reusable snippets defined once in _config.yml and inserted
with {{ name }}. This book defines, among others, {{ course }}.
Source:
> The course is **{{ course }}**.
Rendered:
The course is 15-322 / 15-622 Introduction to Computer Music.
Edit myst_substitutions in _config.yml to add your own.
17. Using this template#
To start a new prose-only chapter:
Copy
content/template.md.Rename it and move it into a
chNN-*/folder.Register it in
_toc.yml.Replace the content with your own.
Before publishing
Remove this Markdown Template page from _toc.yml — it is an author
reference, not course content.
See also
For pages that need to execute Pyquist code at build time, start from the notebook template instead.
18. Custom roles: vocabulary and units#
Two book-specific inline shorthands for the book’s house style.
Use {vocab} when introducing a term for the first time. It italicizes the term
and links it to its definition in the Glossary.
Source:
A signal is {vocab}`periodic` if it repeats.
Rendered:
A signal is periodic if it repeats.
Use {unit} to typeset units. One argument renders a single unit; two render a
fraction (numerator over denominator), with the two separated by a comma (or a
slash). Unlike {vocab}, {unit} is not a role: it expands to raw LaTeX
(\text{…} or \frac{\text{…}}{\text{…}}) and does not inject math mode.
Wrap it in $…$ to use it inline, or drop it unwrapped into a $$…$$ block so
it composes with the surrounding equation.
Source:
Inline, wrap it in math: the period is measured in ${unit}`seconds,cycle`$,
frequency in ${unit}`cycles,second`$, and an angle in ${unit}`radians`$.
In display math, drop it in unwrapped:
$$
\text{bitrate} \left[ {unit}`bits,second` \right]
= f_s \left[ {unit}`samples,second` \right] \cdot b \left[ {unit}`bits,sample` \right].
$$
Rendered:
Inline, wrap it in math: the period is measured in \(\frac{\text{seconds}}{\text{cycle}}\), frequency in \(\frac{\text{cycles}}{\text{second}}\), and an angle in \(\text{radians}\).
In display math, drop it in unwrapped:
19. Linking to the Pyquist API#
Use {pyquist} to mention a Pyquist symbol in prose. It renders the name as
inline code spelled the way students write it (pq.…) and links it to the
matching entry in the Pyquist reference. An unknown
symbol warns at build time, so the prose and the library stay in sync.
The display always shows valid, copy-pasteable code, so what you write and what you see can differ:
You write |
Renders as |
Why |
|---|---|---|
|
re-exported at the top level |
|
|
method of a top-level class |
|
|
qualified, since it lives in a submodule |
|
|
author-qualified, shown verbatim |
|
|
a whole submodule |
Source:
In Pyquist, scores are represented using the {pyquist}`score.Score` object, and
each entry is a {pyquist}`Event`. Convert between pitch and frequency with
{pyquist}`frequency_to_pitch` and {pyquist}`pitch_to_frequency`, and slice audio
with {pyquist}`Audio.segment`.
Rendered:
In Pyquist, scores are represented using the pq.score.Score object, and
each entry is a pq.Event. Convert between pitch and frequency with
pq.helper.frequency_to_pitch and pq.helper.pitch_to_frequency, and slice audio
with pq.Audio.segment.
Prefer {pyquist} over a hand-written `pq.Score` whenever you name a real
symbol: it stays a working link as the API moves, and a typo becomes a build
warning instead of dead text. For the library as a whole, the prose
substitution Pyquist (a plain link to its home page) is still the right
tool.
20. Colored text#
Color inline text with the :{color}[…] shorthand, never with a hand-written
<span style="color:…">. Five colors, matching the Okabe-Ito palette:
:{blue}[…], :{green}[…], :{orange}[…], :{pink}[…], :{gray}[…].
Markdown still works inside the brackets, and appending a link target colors
the whole link — underline included. A -highlight suffix
(:{blue-highlight}[…]) renders the text as a highlighter chip on the
matching tint instead of coloring it.
Source:
The schedule legend rides on these: :{blue}[**autograded**] ·
:{green}[**open-ended**] · :{orange}[**exam**] ·
:{pink}[**final project**] · :{gray}[breaks / no class].
To color a link, append its target:
:{pink}[**see the Glossary (due)**](../book/glossary.md).
As highlighter chips: :{blue-highlight}[autograded] ·
:{orange-highlight}[exam] · :{gray-highlight}[breaks].
Rendered:
The schedule legend rides on these: autograded · open-ended · exam · final project · breaks / no class.
To color a link, append its target: see the Glossary (due).
As highlighter chips: autograded · exam · breaks.
The shorthand is a source-read substitution like the unit one in §18
(_ext/icm_roles.py): it expands to the MyST attrs_inline form
[…]{.c-blue} before parsing, so that form works too. The c-* classes are
defined in _static/custom.css.

