Skip to content

audio

Web Audio components for playing, analyzing, and recording sound.

Provides five components built on the browser's Web Audio API:

  • :class:Tone: play a single pitch (a note name like "C4" or a frequency in Hz) with a chosen waveform.
  • :class:Melody: play a sequence of notes at a tempo; a melody is just a Python list, so students can compose music with list operations.
  • :class:Sound: play an audio file through an optional chain of effects (echo, reverb, muffle, sharpen, distortion) with volume/pan/speed control.
  • :class:Microphone: monitor live microphone input, firing events when the room gets loud or quiet and providing an :class:AudioLevel snapshot on form submission.
  • :class:AudioRecorder: record microphone audio and submit it as a :class:Recording that can be played back with :class:Sound.

The Python side only describes the components: each renders as a custom element (<drafter-tone>, <drafter-melody>, <drafter-sound>, <drafter-microphone>, <drafter-audio-recorder>) whose behavior is implemented in js/src/components/. A single shared AudioContext lives in js/src/components/audioBroker.ts; because browsers require a user gesture before sound can play, components rendered before any interaction show a small "Enable sound" prompt (the audio analog of the geolocation permission prompt).

Like :class:~drafter.components.geolocation.CurrentLocation, the :class:Microphone and :class:AudioRecorder components keep a hidden form field (named after the component) updated with JSON-encoded data; converters registered below turn those payloads into :class:AudioLevel and :class:Recording values when a matching route parameter is annotated with them. Failures become status values rather than exceptions, so routes can inspect problems without try/except.

MicrophoneStatus = Literal['unavailable', 'prompt', 'pending', 'granted', 'denied', 'error'] module-attribute

The permission/availability states an AudioLevel's status field can report, mirroring the microphone permission workflow.

NoteValue = str | tuple[str, int | float] module-attribute

One item in a Melody's note list: a note name like "C4" (or "rest"), played for one beat, or a (note, beats) pair like ("C4", 2).

REST = 'rest' module-attribute

A note that plays silence for its beats in a Melody.

RecordingStatus = Literal['unavailable', 'prompt', 'recording', 'granted', 'denied', 'error'] module-attribute

The permission/recording states a Recording's status field can report.

VISUALIZATIONS = ('meter', 'waveform', 'bars') module-attribute

The live visualization styles a Microphone can draw; Sound supports the "waveform" and "bars" subset.

WAVEFORMS = ('sine', 'square', 'triangle', 'sawtooth') module-attribute

The oscillator waveform names accepted by Tone and Melody.

AudioEffect() dataclass

Base class for audio effects that can be chained onto sound.

Effects are plain values, not components: pass a list of them as the effects parameter of :class:Sound, :class:Tone, or :class:Melody, and they are applied in order.

to_config()

Serialize this effect to the JSON configuration the JS side reads.

AudioLevel(status, message=None, volume=None, peak_volume=None, pitch=None) dataclass

A snapshot of microphone input from a :class:Microphone component.

Attributes:

Name Type Description
status MicrophoneStatus

Current permission/availability state.

message str | None

Optional descriptive message about the status.

volume float | None

Loudness from 0.0 (silence) to 1.0 (as loud as the microphone can measure) at the moment the form was submitted, based on the peak signal level (None if unavailable).

peak_volume float | None

The loudest volume heard since the page loaded (None if unavailable).

pitch float | None

The dominant frequency in Hz of the sound being heard (None if unavailable or too quiet to estimate).

AudioRecorder(name, max_duration=30000, show=True, on_record=None, on_denied=None, on_error=None, **extra_settings) dataclass

Bases: Component

Records microphone audio and submits it with the form.

Shows a record button; after asking for microphone permission (shared with :class:Microphone), it records until stopped or until max_duration milliseconds pass. The completed recording is kept in a hidden form field (named name) as a data URL, so a route parameter with the same name annotated as :class:Recording receives the converted value. Play a recording back by passing its data_url to :class:Sound.

Attributes:

Name Type Description
name str

The form field name that will contain the Recording data.

max_duration int

Maximum recording length in milliseconds. Defaults to 30000 (30 seconds).

show bool

Whether to display the recorder UI. Defaults to True.

on_record UrlOrFunction | None

Function or URL to call when a recording completes.

on_denied UrlOrFunction | None

Function or URL to call when microphone permission is denied.

on_error UrlOrFunction | None

Function or URL to call when recording fails.

Initialize the AudioRecorder component.

Parameters:

Name Type Description Default
name str

The form field name for the Recording data.

required
max_duration int

Maximum recording length in milliseconds.

30000
show bool

Whether to display the recorder UI.

True
on_record UrlOrFunction | None

Function or URL to call when a recording completes.

None
on_denied UrlOrFunction | None

Function or URL to call when permission is denied.

None
on_error UrlOrFunction | None

Function or URL to call when recording fails.

None
**extra_settings

Additional HTML attributes.

{}

Distortion(amount=0.3) dataclass

Bases: AudioEffect

Overdrives the sound for a gritty, fuzzy character.

Attributes:

Name Type Description
amount float

How distorted the sound is, from 0.0 (clean) to 1.0 (heavily distorted). Defaults to 0.3.

Echo(delay=0.3, strength=0.4) dataclass

Bases: AudioEffect

Repeats the sound after a delay, quieter each time.

Attributes:

Name Type Description
delay float

Seconds between repeats. Defaults to 0.3.

strength float

How loud each repeat is relative to the one before, from 0.0 (no echo) to 1.0 (repeats forever). Defaults to 0.4.

Melody(notes, tempo=120, waveform='sine', volume=0.8, auto_play=False, controls=False, show=True, effects=None, on_note=None, on_finish=None, **extra_settings) dataclass

Bases: Component

Plays a sequence of notes at a tempo using the Web Audio API.

A melody is just a list: each item is a note name like "C4" (played for one beat), a (note, beats) pair like ("C4", 2), or "rest" for silence. Notes are scheduled with sample-accurate Web Audio timing, so melodies stay in rhythm.

Note

An on_note handler that returns a full :class:~drafter.Page re-renders the whole page, which stops and resets this melody after its very first note. To react to notes while the melody keeps playing, return an Update (change state only) or a Fragment targeting another element; save full pages for on_finish.

Attributes:

Name Type Description
notes list[NoteValue]

The notes to play, in order.

tempo int | float

Speed in beats per minute. Defaults to 120.

waveform str

The shape of the sound wave: "sine", "square", "triangle", or "sawtooth". Defaults to "sine".

volume float

Loudness from 0.0 to 1.0. Defaults to 0.8.

auto_play bool

Whether to play as soon as the page loads instead of showing a play button. Defaults to False.

controls bool

Whether to show play/pause and restart buttons. Defaults to False.

show bool

Whether to display the component. Defaults to True. A hidden auto-play component still shows its "Enable sound" prompt while the browser is blocking sound.

effects list[AudioEffect] | None

Optional list of effects (like :class:Echo) applied in order.

on_note UrlOrFunction | None

Function or URL to call as each note starts.

on_finish UrlOrFunction | None

Function or URL to call when the melody finishes.

Initialize the Melody component.

Parameters:

Name Type Description Default
notes list[NoteValue]

List of note names like 'C4', (note, beats) pairs, or 'rest'.

required
tempo int | float

Speed in beats per minute.

120
waveform str

"sine", "square", "triangle", or "sawtooth".

'sine'
volume float

Loudness from 0.0 to 1.0.

0.8
auto_play bool

Whether to play on page load instead of showing a button.

False
controls bool

Whether to show play/pause and restart buttons.

False
show bool

Whether to display the component.

True
effects list[AudioEffect] | None

Optional list of effects applied in order.

None
on_note UrlOrFunction | None

Function or URL to call as each note starts.

None
on_finish UrlOrFunction | None

Function or URL to call when the melody finishes.

None
**extra_settings

Additional HTML attributes.

{}

get_attributes(context)

Extend the base attributes with normalized, JSON-encoded data.

The note list is normalized to [note, beats] pairs and the effects list is serialized, since the <drafter-melody> custom element parses both from JSON strings.

Parameters:

Name Type Description Default
context

The render context passed through to the base class.

required

Returns:

Type Description
dict

The attribute dictionary with notes and effects JSON-encoded.

Microphone(name, threshold=0.5, cooldown=1000, rate=0, show=True, visualize='meter', on_loud=None, on_quiet=None, on_level=None, on_denied=None, on_error=None, **extra_settings) dataclass

Bases: Component

Monitors live microphone input and reports how loud the room is.

This component follows the same permission workflow as :class:~drafter.components.geolocation.CurrentLocation: it shows an "Enable microphone" prompt, and once permission is granted it displays a live level meter. It keeps a hidden form field (named name) updated with the latest :class:AudioLevel snapshot, so a route parameter with the same name annotated as :class:AudioLevel receives the converted value on any form submission.

The on_loud event is the easiest way to react to sound: it fires when the volume crosses threshold (a clap, a shout), and then not again until cooldown milliseconds have passed. Volume is measured as the peak signal level, so brief sounds like claps register at their full loudness.

Note

An on_loud/on_quiet/on_level handler that returns a full :class:~drafter.Page re-renders the whole page, briefly resetting this component (it re-enables itself, but the meter and peak_volume restart). For frequent events, prefer returning an Update (change state only) or a Fragment targeting another element.

Attributes:

Name Type Description
name str

The form field name that will contain the AudioLevel data.

threshold float

The loudness (0.0 to 1.0) that counts as "loud". Defaults to 0.5.

cooldown int

Minimum milliseconds between on_loud events. Defaults to 1000.

rate int

Milliseconds between on_level events, or 0 to never fire them. Defaults to 0.

show bool

Whether to display the permission UI and meter. Defaults to True.

visualize str

The live display once granted: "meter", "waveform", or "bars". Defaults to "meter".

on_loud UrlOrFunction | None

Function or URL to call when the volume rises past threshold.

on_quiet UrlOrFunction | None

Function or URL to call when the volume falls back below threshold.

on_level UrlOrFunction | None

Function or URL to call every rate milliseconds with the current volume.

on_denied UrlOrFunction | None

Function or URL to call when microphone permission is denied.

on_error UrlOrFunction | None

Function or URL to call when the microphone fails.

Initialize the Microphone component.

Parameters:

Name Type Description Default
name str

The form field name for the AudioLevel data.

required
threshold float

The loudness (0.0 to 1.0) that counts as "loud".

0.5
cooldown int

Minimum milliseconds between on_loud events.

1000
rate int

Milliseconds between on_level events (0 disables them).

0
show bool

Whether to display the permission UI and meter.

True
visualize str

"meter", "waveform", or "bars".

'meter'
on_loud UrlOrFunction | None

Function or URL to call when volume rises past threshold.

None
on_quiet UrlOrFunction | None

Function or URL to call when volume falls below threshold.

None
on_level UrlOrFunction | None

Function or URL to call on each level report.

None
on_denied UrlOrFunction | None

Function or URL to call when permission is denied.

None
on_error UrlOrFunction | None

Function or URL to call when the microphone fails.

None
**extra_settings

Additional HTML attributes.

{}

Muffle(amount=0.5) dataclass

Bases: AudioEffect

Removes high frequencies, like hearing sound through a wall.

Attributes:

Name Type Description
amount float

How muffled the sound is, from 0.0 (unchanged) to 1.0 (very muffled). Defaults to 0.5.

Recording(status, message=None, data_url=None, duration=None, size=None) dataclass

A completed audio recording from an :class:AudioRecorder component.

The data_url can be handed directly to :class:Sound (or :class:~drafter.components.media.Audio) to play the recording back.

Attributes:

Name Type Description
status RecordingStatus

Current permission/recording state.

message str | None

Optional descriptive message about the status.

data_url str | None

The recorded audio as a data URL (None if nothing has been recorded).

duration float | None

Length of the recording in seconds (None if unavailable).

size int | None

Size of the recorded audio in bytes (None if unavailable).

Reverb(amount=0.5) dataclass

Bases: AudioEffect

Makes the sound ring out as if played in a large room.

Attributes:

Name Type Description
amount float

How much reverberation to add, from 0.0 (none) to 1.0 (cavernous). Defaults to 0.5.

Sharpen(amount=0.5) dataclass

Bases: AudioEffect

Removes low frequencies, like a tinny phone speaker.

Attributes:

Name Type Description
amount float

How thinned-out the sound is, from 0.0 (unchanged) to 1.0 (very tinny). Defaults to 0.5.

Sound(src, volume=1.0, pan=0.0, speed=1.0, loop=False, effects=None, auto_play=False, controls=True, visualize=None, on_play=None, on_finish=None, on_error=None, **extra_settings) dataclass

Bases: Component

Plays an audio file through the Web Audio API with optional effects.

Unlike the plain :class:~drafter.components.media.Audio component, Sound routes the audio through a processing chain, so it can change volume, stereo position, and playback speed, and apply effects like :class:Echo or :class:Reverb. The data_url of a :class:Recording can be played back this way, too.

Attributes:

Name Type Description
src str

URL (or data URL) of the audio to play.

volume float

Loudness from 0.0 to 1.0. Defaults to 1.0.

pan float

Stereo position from -1.0 (left) to 1.0 (right). Defaults to 0.0.

speed float

Playback speed multiplier; below 1.0 is slower and deeper, above 1.0 is faster and higher. Defaults to 1.0.

loop bool

Whether to repeat forever. Defaults to False.

effects list[AudioEffect] | None

Optional list of effects (like :class:Echo) applied in order.

auto_play bool

Whether to start playing as soon as the page loads. Defaults to False.

controls bool

Whether to show playback controls. Defaults to True.

visualize str | None

Optional live visualization drawn while playing: "waveform" or "bars". Defaults to None.

on_play UrlOrFunction | None

Function or URL to call when playback starts.

on_finish UrlOrFunction | None

Function or URL to call when playback finishes.

on_error UrlOrFunction | None

Function or URL to call if the audio cannot be played.

Initialize the Sound component.

Parameters:

Name Type Description Default
src str

URL (or data URL) of the audio to play.

required
volume float

Loudness from 0.0 to 1.0.

1.0
pan float

Stereo position from -1.0 (left) to 1.0 (right).

0.0
speed float

Playback speed multiplier.

1.0
loop bool

Whether to repeat forever.

False
effects list[AudioEffect] | None

Optional list of effects applied in order.

None
auto_play bool

Whether to start playing on page load.

False
controls bool

Whether to show playback controls.

True
visualize str | None

Optional visualization: "waveform" or "bars".

None
on_play UrlOrFunction | None

Function or URL to call when playback starts.

None
on_finish UrlOrFunction | None

Function or URL to call when playback finishes.

None
on_error UrlOrFunction | None

Function or URL to call if the audio cannot play.

None
**extra_settings

Additional HTML attributes.

{}

get_attributes(context)

Extend the base attributes by JSON-encoding the effects list.

Parameters:

Name Type Description Default
context

The render context passed through to the base class.

required

Returns:

Type Description
dict

The attribute dictionary, with effects serialized for the <drafter-sound> custom element.

Tone(pitch, duration=500, waveform='sine', volume=0.8, attack=10, release=50, auto_play=False, show=True, effects=None, on_start=None, on_finish=None, on_error=None, **extra_settings) dataclass

Bases: Component

Plays a single pitch using the browser's Web Audio API.

The pitch can be a note name like "C4" or "F#3", or a raw frequency in Hz like 440. By default the component renders a small play button; with auto_play=True it plays as soon as the page loads (browsers require at least one interaction with the page first, so a tone on the very first page shows an "Enable sound" prompt instead).

Attributes:

Name Type Description
pitch str | int | float

Note name ("C4") or frequency in Hz (440).

duration int

How long the tone plays, in milliseconds. Defaults to 500.

waveform str

The shape of the sound wave: "sine" (smooth), "square" (buzzy), "triangle" (mellow), or "sawtooth" (bright).

volume float

Loudness from 0.0 to 1.0. Defaults to 0.8.

attack int

Milliseconds to fade in (prevents clicks). Defaults to 10.

release int

Milliseconds to fade out. Defaults to 50.

auto_play bool

Whether to play as soon as the page loads instead of showing a play button. Defaults to False.

show bool

Whether to display the component. Defaults to True. A hidden auto-play component still shows its "Enable sound" prompt while the browser is blocking sound.

effects list[AudioEffect] | None

Optional list of effects (like :class:Echo) applied in order.

on_start UrlOrFunction | None

Function or URL to call when the tone starts playing.

on_finish UrlOrFunction | None

Function or URL to call when the tone finishes playing.

on_error UrlOrFunction | None

Function or URL to call if the tone cannot be played.

Initialize the Tone component.

Parameters:

Name Type Description Default
pitch str | int | float

Note name ("C4") or frequency in Hz (440).

required
duration int

How long the tone plays, in milliseconds.

500
waveform str

"sine", "square", "triangle", or "sawtooth".

'sine'
volume float

Loudness from 0.0 to 1.0.

0.8
attack int

Milliseconds to fade in.

10
release int

Milliseconds to fade out.

50
auto_play bool

Whether to play on page load instead of showing a button.

False
show bool

Whether to display the component.

True
effects list[AudioEffect] | None

Optional list of effects applied in order.

None
on_start UrlOrFunction | None

Function or URL to call when the tone starts.

None
on_finish UrlOrFunction | None

Function or URL to call when the tone finishes.

None
on_error UrlOrFunction | None

Function or URL to call if the tone cannot play.

None
**extra_settings

Additional HTML attributes.

{}

get_attributes(context)

Extend the base attributes by JSON-encoding the effects list.

Parameters:

Name Type Description Default
context

The render context passed through to the base class.

required

Returns:

Type Description
dict

The attribute dictionary, with effects serialized for the <drafter-tone> custom element.

convert_audio_level(ctx)

Convert a JSON string or dict payload into an :class:AudioLevel.

convert_recording(ctx)

Convert a JSON string or dict payload into a :class:Recording.

note_to_frequency(note)

Convert a note name like "C4", "F#3", or "Bb2" to Hz.

Uses equal temperament with A4 = 440 Hz. Note names are a letter A-G, an optional # (sharp) or b (flat), and an octave digit 0-9.

Parameters:

Name Type Description Default
note str

The note name to convert.

required

Returns:

Type Description
float

The frequency in Hz.

Raises:

Type Description
StudentFacingError

If the note name is not recognized.