Skip to main content

aldakit

PyPI version Python 3.10+ License: MIT

A Python parser and MIDI generator for the Alda music programming language, with no install-time dependencies1.

Features

  • Alda Parser - Full parser for the Alda music language with AST generation

  • MIDI Playback - Low-latency playback via libremidi (CoreMIDI, ALSA, WinMM)

  • Audio Playback - Built-in synthesis via TinySoundFont (no external synth required)

  • MIDI Export - Save compositions as Standard MIDI Files

  • Audio Export - Render a score to a WAV file, many times faster than real time

  • MIDI Import - Load MIDI files and convert to Alda notation

  • Alda Export - Serialize any AST back to Alda source, round-trip safe

  • Real-time Transcription - Record from MIDI keyboards and convert to Alda

  • Programmatic Composition - Build music with Python using the compose module

  • Music Theory - Scale, chord, and interval utilities

  • Transformers - Transpose, invert, augment, diminish, and more

  • Generative Music - Markov chains, L-systems, cellular automata, Euclidean rhythms

  • Interactive REPL - Syntax highlighting, auto-completion, and live playback

  • Score Checking - aldakit lint and aldakit info report what will sound wrong before you play it

  • SoundFont Management - Find, download and verify SoundFonts from the CLI

  • CLI Tools - Play, transcribe, and convert from the command line

Installation

Requires Python 3.10+

pip install aldakit

Or with uv:

uv add aldakit

Quick Start

Command Line

# Interactive REPL (default when no args)
aldakit

# Evaluate inline code
aldakit eval "piano: c d e f g"

# Play an Alda file
aldakit play examples/twinkle.alda

# Export to MIDI file
aldakit play examples/bach-prelude.alda -o bach.mid

# Use built-in audio (TinySoundFont) instead of MIDI
aldakit play -sf ~/Music/sf2/FluidR3_GM.sf2 examples/twinkle.alda
aldakit repl -sf ~/Music/sf2/FluidR3_GM.sf2

# Use audio backend with pre-configured soundfont (from config or env)
aldakit play -a examples/twinkle.alda
aldakit repl -a

# Create virtual MIDI port with custom name
aldakit repl -vp MyMIDI

# Get a SoundFont for the built-in audio backend
aldakit soundfont install

# Inspect or check a score without playing it
aldakit info examples/twinkle.alda
aldakit lint examples/twinkle.alda

Python API

import aldakit

# Play directly
aldakit.play("piano: c d e f g")

# Save to MIDI file
aldakit.save("piano: c d e f g", "output.mid")

# Render to audio, faster than real time and without an audio device
aldakit.render("piano: c d e f g", "output.wav")

# Play from file
aldakit.play_file("song.alda")

# List available MIDI ports
print(aldakit.list_ports())

For more control, use the Score class:

from aldakit import Score

score = Score("""
piano:
  (tempo 120)
  o4 c4 d e f | g a b > c
""")

# Play, blocking until finished
score.play(port="FluidSynth")

# Or play in the background and keep control of the playback
handle = score.play(port="FluidSynth", wait=False)
handle.is_playing()
handle.stop()

# Save to file
score.save("output.mid")

# Render to a WAV file
score.render("output.wav")

# Access internals
print(f"Duration: {score.duration}s")
print(score.ast)   # Parsed AST
print(score.midi)  # MIDI sequence

Concurrent Playback

Layer multiple sequences for polyphonic REPL-style playback:

from aldakit.midi.backends import LibremidiBackend

# Create backend with concurrent mode (default)
backend = LibremidiBackend(concurrent=True)

# Play multiple sequences - they layer on top of each other
backend.play(score1.midi)  # Starts immediately
backend.play(score2.midi)  # Layers on top of score1
backend.play(score3.midi)  # Up to 8 concurrent slots

# Check status
print(f"Active slots: {backend.active_slots}")
print(f"Playing: {backend.is_playing()}")

# Wait for all playback to complete
backend.wait()

# Or stop all playback immediately
backend.stop()

# Sequential mode - each play waits for previous to finish
backend.concurrent_mode = False
backend.play(score1.midi)  # Plays first
backend.play(score2.midi)  # Waits, then plays second

MIDI Import

Import existing MIDI files and work with them as Alda:

from aldakit import Score

# Import a MIDI file
score = Score.from_midi_file("recording.mid")

# Or use from_file (auto-detects .mid/.midi)
score = Score.from_file("song.mid")

# View as Alda source
print(score.to_alda())
# piano:
# o4 c4 d e f | g a b > c

# Play the imported MIDI
score.play()

# Export to Alda file
score.save("song.alda")

# Re-export to MIDI
score.save("output.mid")

# Import with custom quantization grid
# Default is 0.25 (16th notes), use 0.5 for 8th notes
score = Score.from_midi_file("recording.mid", quantize_grid=0.5)

Features:

  • Multi-track MIDI files (each channel becomes a separate part, and stays on its own channel when played or re-exported)

  • Channel 10 is imported as a midi-percussion part

  • Tempo detection and preservation

  • General MIDI instrument mapping across all 128 programs

  • Chord detection for simultaneous notes

  • Configurable timing quantization

Real-Time MIDI Transcription

Record MIDI input from a keyboard or controller:

import aldakit

# List available MIDI input ports
print(aldakit.list_input_ports())

# Record for 10 seconds from the first available port
score = aldakit.transcribe(duration=10)

# Play back what was recorded
score.play()

# Export to Alda source
print(score.to_alda())

# Record with options
score = aldakit.transcribe(
    duration=30,
    port_name="My MIDI Keyboard",
    instrument="piano",
    tempo=120,
    quantize_grid=0.25,  # Quantize to 16th notes
)

For more control, use TranscribeSession:

from aldakit.midi.transcriber import TranscribeSession

session = TranscribeSession(quantize_grid=0.25, default_tempo=120)

# Set a callback for note events (optional)
session.on_note(lambda pitch, vel, on: print(f"Note: {pitch}, vel={vel}, on={on}"))

# Start recording
session.start()

# Poll periodically (in a loop or timer)
import time
for _ in range(100):
    session.poll()
    time.sleep(0.1)

# Stop and get the recorded notes
seq = session.stop()
print(seq.to_alda())

Programmatic Composition

Build music programmatically using the compose module:

from aldakit import Score
from aldakit.compose import part, note, rest, chord, seq, tempo, volume

# Create a score from compose elements
score = Score.from_elements(
    part("piano"),
    tempo(120),
    note("c", duration=4),
    note("d"),
    note("e"),
    chord("c", "e", "g", duration=2),
)
score.play()

# Builder pattern with method chaining
score = (
    Score.from_elements(part("violin"))
    .with_tempo(90)
    .add(note("g", duration=8), note("a"), note("b"))
)

# Note transformations
c = note("c", duration=4)
c_sharp = c.sharpen()           # C#
c_up_octave = c.transpose(12)   # Up one octave

# Repeat syntax
pattern = seq(note("c"), note("d"), note("e"))
repeated = pattern * 4  # Repeat 4 times

# Export to Alda source
print(score.to_alda())  # "violin: (tempo 90) g8 a b"

Available compose elements:

  • Notes: note("c", duration=4, octave=5, accidental="+", dots=1)

  • Rests: rest(duration=4), rest(ms=500)

  • Chords: chord("c", "e", "g"), chord(note("c"), note("e", accidental="+"))

  • Sequences: seq(note("c"), note("d")), Seq.from_alda("c d e")

  • Parts: part("piano"), part("violin", alias="v1")

  • Attributes: tempo(120), volume(80), octave(5), panning(50)

  • Dynamics: pp(), p(), mp(), mf(), f(), ff()

  • Advanced: cram(), voice(), voice_group(), var(), var_ref(), marker(), at_marker()

Accidentals use Alda's characters: "+" (sharp), "-" (flat), "_" (natural), repeated for double accidentals. Anything else raises ValueError.

The octave a note declares is preserved through both to_alda() and MIDI generation. Octave is stateful in Alda, so a note only emits an octave change where the octave actually changes:

from aldakit import Score
from aldakit.compose import part, note

score = Score.from_elements(part("piano"), note("c", octave=5), note("d"))
print(score.to_alda())  # 'piano: o5 c d'
print([n.pitch for n in score.midi.notes])  # [72, 74]

Instrument Names

All 128 General MIDI programs are available under their Alda names. Canonical names carry the midi- prefix, and most have shorter aliases:

midi-acoustic-grand-piano:  # canonical
piano:                      # alias for the same program
midi-square-lead:           # synth lead
midi-percussion:            # drum kit on MIDI channel 10

See docs/alda-language/list-of-instruments.md for the full list. An unrecognised instrument name falls back to acoustic grand piano and reports a warning rather than failing silently:

score = Score("bogus-instrument: c d e")
print([str(d) for d in score.diagnostics])
# ["<input>:1:1: Unknown instrument 'bogus-instrument'; falling back to acoustic grand piano."]

midi-percussion (alias percussion) is placed on MIDI channel 10, where note numbers select drum sounds; key signatures and transposition do not apply to it. Melodic parts never use that channel.

That leaves 15 channels for pitched parts, but a score is not limited to 15 of them: a part only holds a channel while it is sounding, so a part that has finished hands its channel to one that is about to start, and the instrument, pan and volume are set again for the part taking over. This is how examples/all-instruments.alda plays all 128 General MIDI instruments. Scores that fit without reuse keep one channel per part, in declaration order. A diagnostic is reported only when more than 15 pitched parts sound at the same moment, which no amount of reuse can accommodate.

Inspecting and Checking a Score

The problems the generator finds are available as values, not just as CLI output, so a build step or an editor plugin can use them:

from aldakit import inspect_score, lint_score

info = inspect_score("piano: c d e\ncello: c2")
print(info.note_count, info.duration)
for part in info.parts:
    print(part.name, part.instrument, part.channel, part.note_count)

for finding in lint_score("piano: nosuchvar"):
    print(finding.severity, finding.code, finding.message)
    # error undefined-variable Undefined variable 'nosuchvar'.

lint_score() reports unknown instruments and attributes, undefined variables and markers, notes clamped into the MIDI range, unused and redefined variables, and parts that collide on a channel. Each finding carries a code, a severity and the source position. The aldakit info and aldakit lint commands are thin wrappers over these two functions.

Scales and Chords

Build melodies and harmonies using music theory helpers:

from aldakit import Score
from aldakit.compose import part, tempo
from aldakit.compose import (
    # Scale functions
    scale, scale_notes, scale_degree, mode,
    relative_minor, relative_major,
    # Chord builders
    major, minor, dim, aug, maj7, min7, dom7,
    arpeggiate, invert_chord, voicing,
)

# Get scale pitches
c_major = scale("c", "major")       # ['c', 'd', 'e', 'f', 'g', 'a', 'b']
a_blues = scale("a", "blues")       # ['a', 'c', 'd', 'd+', 'e', 'g']

# Generate scale as playable notes
melody = scale_notes("c", "pentatonic", duration=8)

# Key relationships
rel_min = relative_minor("c")  # 'a' (C major -> A minor)
rel_maj = relative_major("a")  # 'c' (A minor -> C major)

# Build chords
c_maj = major("c")                    # C E G
a_min7 = min7("a")                    # A C E G
g_dom7 = dom7("g", inversion=1)       # B D F G (first inversion)

# Arpeggiate a chord
arp = arpeggiate(maj7("c"), pattern=[0, 1, 2, 3, 2, 1], duration=16)

# Custom voicing (spread chord across octaves)
spread = voicing(major("c"), [3, 4, 5])  # C3 E4 G5

# Create a I-IV-V-I progression
pitches = scale("c", "major")
progression = [
    major(pitches[0], duration=2),  # C major (I)
    major(pitches[3], duration=2),  # F major (IV)
    major(pitches[4], duration=2),  # G major (V)
    major(pitches[0], duration=1),  # C major (I)
]

score = Score.from_elements(
    part("piano"),
    tempo(100),
    *progression,
)
score.play()

Available scales: major, minor, harmonic-minor, melodic-minor, pentatonic, blues, chromatic, whole-tone, dorian, phrygian, lydian, mixolydian, locrian, japanese, arabic, hungarian-minor, spanish, bebop-dominant, bebop-major

Available chords: major, minor, dim, aug, sus2, sus4, maj7, min7, dom7, dim7, half_dim7, min_maj7, aug7, maj6, min6, dom9, maj9, min9, add9, power

Transformers

Transform sequences with pitch and structural operations:

from aldakit.compose import (
    note, seq,
    transpose, invert, reverse, shuffle,
    augment, diminish, fragment, loop, interleave,
    pipe,
)

# Create a motif
motif = seq(note("c", duration=8), note("d", duration=8), note("e", duration=8))

# Pitch transformers
up_fourth = transpose(motif, 5)      # Transpose up 5 semitones
inverted = invert(motif)             # Invert intervals around first note
backwards = reverse(motif)           # Retrograde

# Structural transformers
longer = augment(motif, 2)           # Double durations (8th -> quarter)
shorter = diminish(motif, 2)         # Halve durations (8th -> 16th)
first_two = fragment(motif, 2)       # Take first 2 elements
repeated = loop(motif, 4)            # Repeat 4 times (explicit)

# Chain transformations with pipe
result = pipe(
    motif,
    lambda s: transpose(s, 5),
    reverse,
    lambda s: augment(s, 2),
)

# All transforms preserve to_alda() export
print(result.to_alda())

MIDI Transformers

For post-MIDI-generation processing, use MIDI-level transformers that operate on absolute timing:

from aldakit import Score
from aldakit.midi.transform import (
    quantize, humanize, swing, stretch,
    accent, crescendo, normalize,
    filter_notes, trim, merge,
)

# Get MIDI sequence from a score
score = Score("piano: c d e f g a b > c")
midi_seq = score.midi

# Timing transformers
quantized = quantize(midi_seq, grid=0.25, strength=0.8)  # Snap to quarter-note grid
humanized = humanize(midi_seq, timing=0.02, velocity=10)  # Add subtle variations
swung = swing(midi_seq, grid=0.5, amount=0.3)            # Apply swing feel

# Velocity transformers
accented = accent(midi_seq, pattern=[1.0, 0.5, 0.5, 0.5])  # 4/4 accent pattern
crescendo_seq = crescendo(midi_seq, start_velocity=50, end_velocity=100)
normalized = normalize(midi_seq, target=100)

# Filtering and combining
filtered = filter_notes(midi_seq, lambda n: n.pitch >= 60)  # Keep notes >= middle C
trimmed = trim(midi_seq, start=0.0, end=2.0)               # First 2 seconds
merged = merge(midi_seq, another_seq)                       # Combine sequences

Note: MIDI transformers operate on absolute timing (seconds) and cannot be converted back to Alda notation.

Generative Functions

Create algorithmic compositions with generative functions:

from aldakit import Score
from aldakit.compose import part, tempo
from aldakit.compose.generate import (
    random_walk, euclidean, markov_chain, lsystem, cellular_automaton,
    shift_register, turing_machine,
)

# Random walk melody
melody = random_walk("c", steps=16, intervals=[-2, -1, 1, 2], duration=8, seed=42)

# Euclidean rhythms (e.g., Cuban tresillo: 3 hits over 8 steps)
rhythm = euclidean(hits=3, steps=8, pitch="c", duration=16)

# Markov chain
chain = markov_chain({
    "c": {"d": 0.5, "e": 0.3, "g": 0.2},
    "d": {"e": 0.6, "c": 0.4},
    "e": {"c": 0.5, "g": 0.5},
    "g": {"c": 1.0},
})
markov_melody = chain.generate(start="c", length=16, duration=8, seed=42)

# L-System (Fibonacci pattern)
from aldakit.compose import note, rest
fib = lsystem(
    axiom="A",
    rules={"A": "AB", "B": "A"},
    iterations=5,
    note_map={"A": note("c", duration=8), "B": note("e", duration=8)},
)

# Cellular automaton (Rule 110)
automaton = cellular_automaton(rule=110, width=8, steps=4, pitch_on="c", duration=16)

# Shift register (LFSR) - classic analog sequencer
lfsr = shift_register(16, bits=4, scale=["c", "e", "g", "b"], duration=16)

# Turing Machine - evolving loop (probability=0 for locked, higher for chaos)
turing = turing_machine(32, bits=8, probability=0.1, seed=42)

# Combine into a score
score = Score.from_elements(
    part("piano"),
    tempo(120),
    *melody.elements,
)
score.play()

CLI Reference

aldakit [--version] [-h] {repl,play,eval,info,lint,ports,soundfont,transcribe} ...

Subcommands

Command Description
(none) Opens the interactive REPL (default when no args)
repl Interactive REPL with syntax highlighting and auto-completion
play Play an Alda file
eval Evaluate Alda code directly
info Summarise a score: parts, instruments, channels, duration
render Render a score to a WAV file, faster than real time
lint Report problems in a score without playing it
ports List available MIDI ports (both input and output)
soundfont Find, download and verify SoundFonts for the audio backend
transcribe Record MIDI input and output Alda code

Global Options

Option Description
--version Show version number and exit
-h, --help Show help message

play Subcommand

aldakit play [-v] [-e CODE] [-o FILE] [--port NAME|INDEX] [-sf FILE] [-a] [-vp NAME] [--stdin] [--parse-only] [--no-wait] FILE
Option Description
FILE Alda file to play (use - for stdin)
-e, --eval CODE Play Alda code given on the command line instead of a file
-v, --verbose Verbose output
-o, --output FILE Save to MIDI file instead of playing
--port NAME|INDEX MIDI port by name or index (see aldakit ports)
-sf, --soundfont FILE Use TinySoundFont audio backend with specified SoundFont
-a, --audio Use audio backend with pre-configured soundfont
-vp, --virtual-port NAME Custom virtual MIDI port name (default: AldakitMIDI)
--stdin Read from stdin (blank line to play)
--parse-only Print AST without playing
--no-wait Return without waiting for playback to finish (playback stops when the command exits)

eval Subcommand

aldakit eval [-v] [-o FILE] [-p NAME|INDEX] [-sf FILE] [-a] [-vp NAME] [--parse-only] [--no-wait] CODE
Option Description
CODE Alda code to evaluate
-v, --verbose Verbose output
--parse-only Print AST without playing
--no-wait Return without waiting for playback to finish
-o, --output FILE Save to MIDI file instead of playing
-p, --port NAME|INDEX MIDI port by name or index
-sf, --soundfont FILE Use TinySoundFont audio backend
-a, --audio Use audio backend with pre-configured soundfont
-vp, --virtual-port NAME Custom virtual MIDI port name (default: AldakitMIDI)

repl Subcommand

aldakit repl [-v] [--port NAME|INDEX] [-sf FILE] [-a] [-vp NAME] [--sequential] [FILE]
Option Description
FILE Alda file to load on startup (use :play to hear it)
-v, --verbose Verbose output
--port NAME|INDEX MIDI port by name or index
-sf, --soundfont FILE Use TinySoundFont audio backend
-a, --audio Use audio backend with pre-configured soundfont
-vp, --virtual-port NAME Custom virtual MIDI port name (default: AldakitMIDI)
--sequential Start in sequential mode (wait for each input)

soundfont Subcommand

The audio backend needs a General MIDI SoundFont. This finds, fetches and checks them; downloads land in ~/.aldakit/soundfonts/ and are verified against a SHA256 checksum.

aldakit soundfont list              # installed files and the download catalog
aldakit soundfont install           # fetch the default (TimGM6mb, 5.8 MB)
aldakit soundfont install FluidR3_GM --force
aldakit soundfont install --all
aldakit soundfont verify            # re-check the downloaded files
aldakit soundfont path              # print the one playback would use

If you ask for audio playback and no SoundFont can be found, aldakit offers to download one, so the usual first run is a single prompt rather than an error. Non-interactive runs (scripts, CI) get the error instead of a prompt.

info Subcommand

aldakit info song.alda
aldakit info -e "piano: c d e"

Prints the parts, their instruments, MIDI programs, channels and note counts, along with the tempo, duration, variables and markers:

song.alda
  parts:    2
  notes:    5
  duration: 0:02.0 (2.00s)
  tempo:    90 bpm

  part   instrument                 prog  chan   notes
  ---------------------------------------------------
  piano  midi-acoustic-grand-piano     0     0       3
  cello  midi-cello                   42     1       2

render Subcommand

aldakit render song.alda                  # writes song.wav
aldakit render song.alda -o out.wav
aldakit render -e "piano: c d e" -o scale.wav
aldakit render song.alda --gain 0.5 --tail 2

Synthesizes the score with a SoundFont and writes a 16-bit stereo WAV, with no audio device involved and without waiting for the score to play: a two and a half minute score renders in about twelve seconds. The synthesis is the same code path playback uses, so the file and the speakers agree.

Option Description
-o, --output FILE Output file (default: the input file with a .wav suffix)
-sf, --soundfont FILE SoundFont to synthesize with (default: the one playback uses)
-g, --gain GAIN Volume factor, 0.0 to 2.0, where 1.0 is unity
--tail SECONDS Audio rendered after the last note, so release tails are not cut off

A mix loud enough to clip is reported along with a gain that will not:

Warning: the mix peaked at 2.15 of full scale and was clipped. Try --gain 0.46.

lint Subcommand

aldakit lint song.alda
aldakit lint -e "piano: c" --strict

Reports what will make a score sound wrong without playing it: unknown instruments, undefined variables and markers, unknown attributes, notes clamped into the MIDI range, unused variables, and parts that collide on a channel.

Option Description
FILE Alda file to check (use - for stdin)
-e, --eval CODE Check Alda code given on the command line
-q, --quiet Print nothing; report through the exit status
--strict Exit non-zero on warnings as well as errors

Exit status is 0 when clean, 1 when an error was found (or any finding under --strict), and 2 when the score does not parse -- so aldakit lint --strict works as a build step.

transcribe Subcommand

aldakit transcribe [-d SEC] [-i INST] [-t BPM] [-q GRID] [-o FILE] [--port NAME] [--play] [-v] [--alda-notes] [--feel FEEL] [--swing-ratio RATIO]
Option Description
-d, --duration SEC Recording duration in seconds (default: 10)
-i, --instrument NAME Instrument name (default: piano)
-t, --tempo BPM Tempo for quantization (default: 120)
-q, --quantize GRID Quantize grid in beats (default: 0.25 = 16th notes)
-o, --output FILE Save to file (.alda or .mid)
--port NAME MIDI input port name
--play Play back the recording after transcription
-v, --verbose Show notes as they are played
--alda-notes Show notes in Alda notation (with -v)
--feel FEEL Rhythm feel: straight, swing, triplet, quintuplet
--swing-ratio RATIO Swing ratio between 0 and 1 (default: 0.67)

Examples

# Interactive REPL (default when no args)
aldakit
aldakit repl

# Evaluate inline code
aldakit eval "piano: c d e f g"

# Play a file
aldakit play examples/jazz.alda
aldakit play -v examples/jazz.alda  # verbose

# Play to a specific port (by index or name)
aldakit play --port 0 examples/twinkle.alda
aldakit play --port FluidSynth examples/twinkle.alda

# Use built-in audio (TinySoundFont) instead of MIDI
aldakit play -sf ~/Music/sf2/FluidR3_GM.sf2 examples/twinkle.alda
aldakit repl -sf ~/Music/sf2/FluidR3_GM.sf2

# Read from stdin
echo "piano: c d e f g" | aldakit play -
aldakit play --stdin

# Parse and show AST
aldakit play --parse-only examples/twinkle.alda
aldakit eval --parse-only "piano: c/e/g"

# Export to MIDI file
aldakit play examples/twinkle.alda -o twinkle.mid
aldakit eval "piano: c d e f g" -o output.mid

# List available MIDI ports
aldakit ports
aldakit ports -o  # output ports only
aldakit ports -i  # input ports only

# Record MIDI input for 10 seconds (default)
aldakit transcribe

# Record from a specific input port
aldakit transcribe --port 0
aldakit transcribe --port "My MIDI Keyboard"

# Record for 30 seconds with verbose note display
aldakit transcribe -d 30 -v

# Record with Alda-style note display
aldakit transcribe -d 10 -v --alda-notes

# Record and save to file
aldakit transcribe -o recording.alda
aldakit transcribe -o recording.mid

# Record and play back
aldakit transcribe --play

# Record with custom settings (swing feel, triplet quantization)
aldakit transcribe -d 20 -t 90 -i guitar --feel triplet --play

Configuration File

aldakit supports INI-format configuration files to set default values for common options. Configuration is loaded from these locations (in priority order):

  1. ./aldakit.ini - Project-local config (current working directory)

  2. ~/.aldakit/config.ini - User config (home directory)

  3. ALDAKIT_SOUNDFONT environment variable (for soundfont only)

CLI arguments always override config file settings.

Example Configuration

Create ~/.aldakit/config.ini:

[aldakit]
# Default SoundFont for audio backend
soundfont = ~/Music/sf2/FluidR3_GM.sf2

# Default backend: "midi" or "audio"
backend = midi

# Default MIDI output port (name or index)
port = FluidSynth

# Default tempo for REPL (BPM)
tempo = 120

# Enable verbose output by default
verbose = false

Available Options

Option Type Default Description
soundfont path none SoundFont path for audio backend
backend string midi midi = external synths/DAWs/virtual port; audio = built-in TinySoundFont
port string none Default MIDI output port name
tempo integer 120 Default tempo for REPL (BPM)
verbose boolean false Enable verbose output

Backend values:

  • midi (default): Uses libremidi for MIDI output. Sends to external synthesizers (FluidSynth, hardware), DAWs, or creates a virtual port ("AldakitMIDI") for routing.

  • audio: Uses built-in TinySoundFont for direct audio output. Requires a soundfont to be configured. No external MIDI setup needed.

Backend Selection Priority

  1. CLI -sf /path/to/soundfont.sf2 forces the audio backend with that SoundFont

  2. CLI -a / --audio forces the audio backend, using a configured or discovered SoundFont

  3. Config backend = audio uses the audio backend

  4. If MIDI output ports are available, use MIDI (default)

  5. If no MIDI ports are available and a SoundFont can be found, use audio

  6. Otherwise create a virtual MIDI port ("AldakitMIDI") and warn that nothing will be heard until a synth or DAW connects to it

A SoundFont counts as available if it is named by -sf, by soundfont in the config file, or by ALDAKIT_SOUNDFONT, or if one is discovered in a standard location such as ~/.aldakit/soundfonts/ or ~/Music/sf2/.

If aldakit play produces no sound, run aldakit ports to see whether any MIDI destination exists. With no ports and no SoundFont, MIDI is being sent to a virtual port that nothing is listening to.

Project-Local Configuration

Create aldakit.ini in your project directory to override user settings:

[aldakit]
# Use audio backend with project-specific SoundFont
backend = audio
soundfont = ./sounds/project-soundfont.sf2
tempo = 140

Interactive REPL

The REPL provides an interactive environment for composing and playing Alda code:

aldakit repl

Features:

  • Syntax highlighting

  • Auto-completion for instruments (3+ characters)

  • Command history (persistent across sessions)

  • Multi-line paste (use platform-specific paste: ctrl-v, shift-ctrl-v, cmd-v, etc.)

  • Multi-line input (Alt+Enter)

  • MIDI playback control (Ctrl+C to stop)

REPL Commands:

Command Description
:load FILE Load an Alda file (does not play)
:play [FILE] Play the loaded score, or load and play FILE
:save FILE Save the session to .alda or .mid
:ls [DIR] List Alda files and directories
:cd [DIR] Change directory
:pwd Show the current directory
:clear Forget the session so far
:ports List MIDI ports
:instruments List available instruments
:tempo [BPM] Show/set the default tempo
:stop Stop playback
:status Show playback status
:concurrent / :sequential Switch playback mode
:help Show help
:quit Exit the REPL

Open a file directly from the command line. It is loaded, not played, so the REPL is ready immediately:

$ aldakit repl examples/twinkle.alda
Loaded examples/twinkle.alda (1 part, 42 notes, 28.7s)
Type :play to hear it.

aldakit> :play
Playing examples/twinkle.alda...

Working with files inside the REPL:

aldakit> :ls
  examples/
  sketch.alda
aldakit> :load sketch.alda
Loaded sketch.alda (2 parts, 64 notes, 12.4s)
Type :play to hear it.
aldakit> :play
Playing sketch.alda...
aldakit> piano: c d e f g
aldakit> :save take-2.alda
Saved /home/you/music/take-2.alda

:load never plays: a file can be inspected, saved or edited before it is heard, and opening a long score does not tie up the prompt. :play with no argument replays whatever is loaded; :play FILE is shorthand for loading and playing in one step. Typed input still plays as soon as you press Enter.

:save writes everything accepted during the session -- typed, pasted or loaded -- as a single score. A .mid or .midi extension exports MIDI instead. Note that this is the session's source, not a recording of what you heard: in concurrent mode inputs are layered as they play, whereas the saved file is one score read top to bottom.

A file opened with :load (or given on the command line) keeps its own tempo. The REPL only prepends its default tempo to input you type that does not set one.

Alda Syntax Reference

Notes and Rests

piano:
  c d e f g a b   # Notes
  r               # Rest
  c4 d8 e16       # With duration (4=quarter, 8=eighth, etc.)
  c4. d4..        # Dotted notes
  c500ms d2s      # Milliseconds and seconds

Accidentals

c+    # Sharp
c-    # Flat
c_    # Natural
c++   # Double sharp

Octaves

o4 c    # Set octave to 4
> c     # Octave up
< c     # Octave down

Chords

c/e/g           # C major chord
c1/e/g          # Whole note chord
c/e/g/>c        # With octave change

Ties and Slurs

c1~1            # Tied notes (duration adds)
c4~d~e~f        # Slurred notes (legato)

Parts

piano: c d e

violin "v1": c d e    # With alias

violin/viola/cello "strings":   # Multi-instrument
  c d e

Attributes

(tempo 120)     # Set tempo (BPM)
(tempo! 120)    # Global tempo

(vol 80)        # Volume (0-100)
(volume 80)

(quant 90)      # Quantization/legato (0-100)

(panning 50)    # Pan (0=left, 100=right)

# Dynamic markings
(pp) (p) (mp) (mf) (f) (ff)

# Key signatures
(key-sig '(g major))     # G major (F#)
(key-sig '(d minor))     # D minor (Bb)
(key-sig "f+ c+")        # Explicit accidentals

# Transposition
(transpose 5)   # Up 5 semitones
(transpose -2)  # Down 2 semitones (Bb instrument)

Variables

riff = c8 d e f g4

piano:
  riff riff > riff

Repeats

c*4             # Repeat note 4 times
[c d e]*4       # Repeat sequence
[c d e f]*8     # 8 times

Cram (Tuplets)

{c d e}4        # Triplet in quarter note
{c d e f g}2    # Quintuplet in half note
{c {d e} f}4    # Nested cram

Voices

piano:
  V1: c4 d e f
  V2: e4 f g a
  V0:           # End voices

Markers

piano:
  c d e f
  %chorus
  g a b > c

violin:
  @chorus       # Jump to chorus marker
  e f g a

Supported Instruments

All 128 General MIDI instruments are supported. Common examples:

  • piano, acoustic-grand-piano

  • violin, viola, cello, contrabass

  • flute, oboe, clarinet, bassoon

  • trumpet, trombone, french-horn, tuba

  • acoustic-guitar, electric-guitar-clean, electric-bass

  • choir, strings, brass-section

See midi/types.py for the complete mapping.

MIDI Backend

aldakit uses libremidi via nanobind for cross-platform MIDI I/O:

  • Low-latency realtime playback

  • Virtual MIDI port support (AldakitMIDI), makes it easy to just send to your DAW.

  • Pure Python MIDI file writing (no external dependencies)

  • Cross-platform: macOS (CoreMIDI), Linux (ALSA), Windows (WinMM)

  • Supports hardware and software/virtual MIDI ports (FluidSynth, IAC Driver, etc.)

import aldakit

# List available ports
print(aldakit.list_ports())

# Play to virtual port (visible in DAWs like Ableton Live)
aldakit.play("piano: c d e f g")

# Play to a specific port
aldakit.play("piano: c d e f g", port="FluidSynth")

# Save to MIDI file
aldakit.save("piano: c d e f g", "output.mid")

Audio Backend (Built-in)

For self-contained audio playback without external synthesizers, aldakit includes a built-in audio backend powered by TinySoundFont and miniaudio:

  • Direct audio output (no FluidSynth or DAW required)

  • Cross-platform: macOS (CoreAudio), Linux (ALSA/PulseAudio), Windows (WASAPI)

  • Requires a SoundFont file (.sf2) for instrument sounds

  • Header-only libraries for minimal binary size

Basic Usage

from aldakit import Score

# Play with built-in audio (requires SoundFont)
score = Score("piano: c d e f g")
score.play(backend="audio")

# Specify SoundFont explicitly
score.play(backend="audio", soundfont="/path/to/FluidR3_GM.sf2")

SoundFont Setup

The audio backend requires a General MIDI SoundFont file. aldakit searches these locations automatically:

  • $ALDAKIT_SOUNDFONT environment variable

  • ~/Music/sf2/

  • ~/.aldakit/soundfonts/

  • /usr/share/soundfonts/ (Linux)

Option 1: Download manually

Download a SoundFont and place it in a folder such as ~/Music/sf2/. These are mirrored on aldakit's soundfonts-v1 release, which is where aldakit soundfont install fetches them from:

They are third-party works, not part of aldakit; SOUNDFONT-LICENSES.txt on the same release records each licence in full.

Suggest using a sha256sum (macOs or Linux) or similar to verify file integrity after download:

% sha256sum FluidR3_GM.sf2
74594e8f4250680adf590507a306655a299935343583256f3b722c48a1bc1cb0  FluidR3_GM.sf2

% sha256sum GeneralUser-GS.sf2
c278464b823daf9c52106c0957f752817da0e52964817ff682fe3a8d2f8446ce  GeneralUser-GS.sf2

% sha256sum TimGM6mb.sf2
82475b91a76de15cb28a104707d3247ba932e228bada3f47bba63c6b31aaf7a1  TimGM6mb.sf2

On Windows (PowerShell): Get-FileHash -Algorithm SHA256

Option 2: Auto-download

from aldakit.midi.soundfont import setup_soundfont, setup_all_soundfonts

# Downloads TimGM6mb.sf2 (~6 MB) to ~/.aldakit/soundfonts/
setup_soundfont()

# Or download all available SoundFonts from the catalog
setup_all_soundfonts()

Option 3: Using SoundFontManager

For more control, use the SoundFontManager class:

from aldakit.midi.soundfont import SoundFontManager

manager = SoundFontManager()

# Find existing SoundFont
sf = manager.find()

# List all found SoundFonts
for path in manager.list():
    print(path)

# Download a specific SoundFont (with SHA256 verification)
path = manager.download("FluidR3_GM")

# Download all SoundFonts from catalog
paths = manager.setup_all()

# Verify checksums of downloaded files
results = manager.verify_checksums()
for name, valid in results.items():
    print(f"{name}: {'OK' if valid else 'FAILED'}")

# List available downloads
for name, info in manager.list_available_downloads().items():
    print(f"{name}: {info['size_mb']} MB - {info['description']}")

Option 4: Environment variable

export ALDAKIT_SOUNDFONT=/path/to/your/soundfont.sf2

Using TsfBackend Directly

from aldakit import Score
from aldakit.midi.backends import TsfBackend

# Create backend with specific SoundFont
with TsfBackend(soundfont="~/Music/sf2/FluidR3_GM.sf2") as backend:
    score = Score("piano: c/e/g")
    backend.play(score.midi)
    backend.wait()  # Block until playback completes

# Inspect SoundFont presets
backend = TsfBackend()
print(f"Presets: {backend.preset_count}")
for i in range(min(10, backend.preset_count)):
    print(f"  {i}: {backend.preset_name(i)}")

Audio vs MIDI Backend

Feature Audio (backend="audio") MIDI (backend="midi")
External synth required No Yes (FluidSynth, DAW, hardware)
Setup complexity Just needs SoundFont Requires MIDI routing
Sound quality Depends on SoundFont Depends on synth
DAW integration No Yes (virtual port)
Latency Very low Very low
Effects (reverb, etc.) No Depends on synth

Recommendation: Use backend="audio" for quick playback and standalone use. Use backend="midi" (default) for DAW integration, hardware synths, or when you need effects.

MIDI Playback Setup

Virtual Port (Recommended)

When no hardware MIDI ports are available, aldakit creates a virtual port named "AldakitMIDI". This port is visible to DAWs and other MIDI software:

  1. Start the REPL: aldakit repl

  2. In your DAW (Ableton Live, Logic Pro, etc.), look for "AldakitMIDI" in MIDI input settings

  3. Play code in the REPL - notes will be sent to your DAW

Software Synthesizer (FluidSynth)

For high-quality General MIDI playback without hardware, use FluidSynth:

# Install FluidSynth (macOS)
brew install fluidsynth

# Install FluidSynth (Debian/Ubuntu)
sudo apt install fluidsynth 

# Download a SoundFont (e.g., FluidR3_GM.sf2)
# eg. sudo apt install fluid-soundfont-gm
# Place in ~/Music/sf2/

# Start FluidSynth with CoreMIDI (macOS)
fluidsynth -a coreaudio -m coremidi ~/Music/sf2/FluidR3_GM.sf2

# In another terminal, start aldakit
aldakit repl
# aldakit> piano: c d e f g

A helper script is available in the repository:

# Set the SoundFont directory (add to your shell profile)
export ALDAPY_SF2_DIR=~/Music/sf2

# Run with default SoundFont (FluidR3_GM.sf2)
python scripts/fluidsynth-gm.py

# Or specify a SoundFont directly
python scripts/fluidsynth-gm.py /path/to/soundfont.sf2

# List available SoundFonts
python scripts/fluidsynth-gm.py --list

Hardware MIDI

Connect a USB MIDI interface or synthesizer, then:

# List available ports
aldakit ports

# Play to a specific port
aldakit play --port "My MIDI Device" examples/twinkle.alda

MIDI File Export

If you don't have MIDI playback set up, export to a file:

# Save to MIDI file
aldakit play examples/twinkle.alda -o twinkle.mid

# Open with default app
open twinkle.mid

Development

Setup

git clone https://github.com/shakfu/aldakit.git
cd aldakit
make  # Build the libremidi extension

Run Tests

make test
# or
uv run pytest tests/ -v

Golden Fixtures

Two sets of fixtures pin what the examples produce, so that an unintended change shows up as a reviewable diff rather than as music that quietly sounds different:

  • tests/golden/examples.json pins the notes, channels, programs, timings and velocities of every example. Regenerate with make golden.

  • tests/golden/audio.json pins what they sound like: every example is rendered with a checksum-pinned SoundFont and its loudness per channel, peak and length are compared. This catches what MIDI cannot -- an instrument that never sounds because its program change went to the wrong channel, or a pan that never reached the synthesizer. Regenerate with make golden-audio.

The audio fixtures need the SoundFont they are pinned to, which is not in the repository, so they skip if it is absent:

make soundfont     # downloads TimGM6mb (6 MB, checksum verified)
make test-audio    # fails rather than skips if it is missing

CI runs test-audio on Linux and macOS.

Architecture

aldakit architecture

License

MIT

See Also

  • Alda - The original Alda language and reference implementation

  • Alda Cheat Sheet - Syntax reference

  • Extending aldakit - Design document for programmatic API

  • libremidi - A modern C++ MIDI 1 / MIDI 2 real-time & file I/O library. Supports Windows, macOS, Linux and WebMIDI.

  • TinySoundFont - SoundFont2 synthesizer library in a single C/C++ header

  • miniaudio - Single-header audio playback and capture library

  • nanobind - a tiny and efficient C++/Python bindings

  1. Includes a rich REPL, native MIDI, and built-in audio via bundled prompt-toolkit, libremidi, and TinySoundFont respectively.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aldakit-0.3.1.tar.gz (2.3 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

aldakit-0.3.1-cp314-cp314-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.14Windows x86-64

aldakit-0.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (894.1 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.3.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (882.0 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.3.1-cp314-cp314-macosx_11_0_x86_64.whl (830.6 kB view details)

Uploaded CPython 3.14macOS 11.0+ x86-64

aldakit-0.3.1-cp314-cp314-macosx_11_0_arm64.whl (807.5 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

aldakit-0.3.1-cp313-cp313-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.13Windows x86-64

aldakit-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (894.2 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.3.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (881.6 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.3.1-cp313-cp313-macosx_11_0_x86_64.whl (830.5 kB view details)

Uploaded CPython 3.13macOS 11.0+ x86-64

aldakit-0.3.1-cp313-cp313-macosx_11_0_arm64.whl (807.4 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

aldakit-0.3.1-cp312-cp312-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.12Windows x86-64

aldakit-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (894.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.3.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (881.9 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.3.1-cp312-cp312-macosx_11_0_x86_64.whl (830.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ x86-64

aldakit-0.3.1-cp312-cp312-macosx_11_0_arm64.whl (807.5 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

aldakit-0.3.1-cp311-cp311-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.11Windows x86-64

aldakit-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (896.4 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.3.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (884.1 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.3.1-cp311-cp311-macosx_11_0_x86_64.whl (831.8 kB view details)

Uploaded CPython 3.11macOS 11.0+ x86-64

aldakit-0.3.1-cp311-cp311-macosx_11_0_arm64.whl (809.5 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

aldakit-0.3.1-cp310-cp310-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.10Windows x86-64

aldakit-0.3.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (896.9 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.3.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (884.5 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.3.1-cp310-cp310-macosx_11_0_x86_64.whl (832.0 kB view details)

Uploaded CPython 3.10macOS 11.0+ x86-64

aldakit-0.3.1-cp310-cp310-macosx_11_0_arm64.whl (809.8 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file aldakit-0.3.1.tar.gz.

File metadata

  • Download URL: aldakit-0.3.1.tar.gz
  • Upload date:
  • Size: 2.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.3.1.tar.gz
Algorithm Hash digest
SHA256 e76f3a63bab4cfcdac7367e396daa13cd8f5ed865446a30c1372b9502e15f07d
MD5 8d3ae6e26284c524aa84ed8e2c06f60b
BLAKE2b-256 0dc14d7f8b304a02f33281f73628829efc813b0345ac6e897fe6a699314641d7

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.3.1-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.3.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 e41076f6535f419c7ffa5b68b1935cb0b4a5ab2583cd6adb20a771dc32eca2ee
MD5 2a601d79fd671b82f28a5d29338bf391
BLAKE2b-256 020f9993e7ac44a0c39ce3d7df84046995b4390b15538a528038a415e88a2334

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8ddd1e36d75dd87e40ab94fb713e51c95ddb9716e9064e596497d99908024b5d
MD5 2f33a9649b89fa12f05db8e3c2893b95
BLAKE2b-256 dc97d128356c62749b9864c651c0f8fe436d8119f258ce135bffa41e5c239e53

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7db98251815e085a9d2128cf7234f7b3cd6c80d138417747a6926f7a15ec4c33
MD5 30645a0e60717487a2ba39921cc49746
BLAKE2b-256 cd664c0636df5dd3978d8e679c98dbffd54e8f99a53f5e76e9d7be075b26d1f5

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp314-cp314-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp314-cp314-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 09a62b82ba7914e9ba1c3f28f0a2ebaa93173c7aab81805411d7206cc19351e0
MD5 f52b048f8b1defa576295a4d71d98b07
BLAKE2b-256 9a977576f78b1add212f39d0dbbe570f61ef0b1aba94968bd4f0eed29ee45e77

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fb3e203e68b1a778fd207e6f3b53732f1843cf622db47c38e718139a706cdf8f
MD5 f522f0f7dcab4dc2c3638557b8f6d5c6
BLAKE2b-256 c5809a34a998fd9b832bf95d42d1850dd34bfeab906b4dad4529b26bc211fa09

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.3.1-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.3.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 f91392af2cdfff230b891b7441f4700061ebb8945749fe04ca9ee6bf7198c62d
MD5 7088c79784e1f0eef772344bbf4d3fdc
BLAKE2b-256 3290fd08da3aa4a358fc0d66c305841c362774ad73eb571491f1c0f2456cbe4a

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d00425cd8628787be351ead9a7b714f9452ecabde09f51bba07b7de7478d0eaa
MD5 4b6a8ef1ab3ecd1257d566e20b34c1af
BLAKE2b-256 acdedaedf2d5f115cfea9ee0d1a3ffb4c8a3054cfd4a9a08a52a4be254754fe1

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a8393f38bcdf0db3b24be10b5b9dd6e178e4f3d4dde37d327637a598c93d08d1
MD5 777636b44c0281974db833c314485ec0
BLAKE2b-256 624fbda1825a0ee25a2cb9212fad389e666673010b226641a7083e7b948b10a0

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp313-cp313-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp313-cp313-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 317919d152217954d678b98e8a60a11fd44915170e08addc9ec6c28815ee01c0
MD5 4dcc712db468267d686327f0184080d1
BLAKE2b-256 45610e05f067a0170e9b2a0ab7147e5c77b896a5c7d06224294b118ddec5d66b

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7d84165aa6c472d826c09488e3761f029e07e16c113f75a6839ca68a150a08f2
MD5 e6127dd129516d2f12ed6d0c9490c155
BLAKE2b-256 6eb69807a31b9967b81318b9d04936536bf7c33e23863c62df75f61550131864

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.3.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.3.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 27642373b3f100edbb4843c33ecac7a9e48649b3fa12e285390bf5dae50abb1a
MD5 34b646d0766765e2c03111183c684bce
BLAKE2b-256 051102fff45f110260347612c05861f5ca7aa16f32caddc4fd7679b2932b3b13

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b71f915e06d8a5a20b3a6bed5f0f04f88a6880d5c4a5fa9565d8820028247542
MD5 366ccaa6b541e73c640d27d0ed90613f
BLAKE2b-256 c0d98bb8946a41442e854d5d5b9e248e7f0d43c4cc2a1f879034114949823a20

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 84ed6659ee35a6d9889a73d7120cbe72e2b6703f44c0495245f75f0454091d2d
MD5 507410bde567a30f1932b09d6946112b
BLAKE2b-256 5d6cef3002cad71fe53870ff3a21581b8ea78dd93c8fe50c9375b4eacbe1c516

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp312-cp312-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp312-cp312-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 fd5020e1d94dea54bd173934587e2abcbf93b02e2f6dfd641482a435b20c0829
MD5 4385a2c61ed3af7916cb0d5938aa0dfa
BLAKE2b-256 d31dac1118a32ef6fcd765ffdd244fe45e088492829fbe3af99cc70039147138

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b908ba4893e454f91a127063405e0ea9932e48518a952541b8b28d653b7a41f2
MD5 d9736d0418e4c9afc0c5019d9b50b964
BLAKE2b-256 88d9d0ffdb90dd4786bf802d0b0f2143506f7ce384b28197318b5e3e6826fb21

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.3.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.3.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 065fa98e5753e89fdd0d01526d76af281414a621feb795c405c66d94cef5cb48
MD5 2f22e94fcfdacde9c6c1629084339699
BLAKE2b-256 81a1bd01b5173806f6e9cf3edbf320e069a33c74382133306d909a541d7c3b30

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9fce017ebbbbafdee9e1b0ec2f5de874b430fbf82b2a3063a65dfdfae70edf60
MD5 7c2dd9b12bf53c6dd4ab08d6e6affb2d
BLAKE2b-256 4c24fa5d7795137b4551a0f9c692736cb45736897d5162c8d9a3d99774022885

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0aef345fbf92903ea5666ac1683ba3d9649b2d7e22e59bde1cf292c4deab1a9b
MD5 f5b78e428409833ea301586b77aa058a
BLAKE2b-256 5b23329fa0c4d23a199d0ddcd62383f464ac1e9fe652a8c9bb26ee3b74cedb38

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp311-cp311-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 09a11c72b007384af9d92359d23b20e2d808709c7c80acf7f0d6cb5a6d62a223
MD5 9ae9cb09f028396b85f1daba025d6717
BLAKE2b-256 571c9dd6d6a43452439831bfa5c2e05e8becae262871de202d12ab9825582d93

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2fb73825561538519605ba5105b3a27e446bb2e85217bca6658e7a71f31b4906
MD5 43c26ecedd16fc14cf5ab74ccac44c8a
BLAKE2b-256 d451e5371a027889b09f6338f4409a3de621962612bb3cf5a29b75cc993eb88d

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.3.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.3.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 aaeb2055c8fb1c2c01fa0c561a8e4f0a101a633940e8d148210250ea3e77e5b6
MD5 dc37848039714d7e1db90f9334641da4
BLAKE2b-256 2741e6aca421bccd4a9fe72c18e02a0fa5f4511a7a6bdfe2ec39beacf0c2cc8f

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 893772563600c9e0a9f432d2261485f0eeac32b3c5c37005e536c8407a4b7613
MD5 46bd718321a2c88f9faad5bb6af03524
BLAKE2b-256 396084c749a6adddcdae24cf8a2e80ac794988fd08247c94955e201eb47678f1

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c2e20e4945cfb8e33c4de867de6f23b53c738ecb58f0e92643b4357d8e822dd1
MD5 42fcddb1577f3ebb08555e53a6f8e25f
BLAKE2b-256 2d23517621c0663f7be3f06df7dd1b2f2292670fed56817db5f53e38ed576ac9

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp310-cp310-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp310-cp310-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 ee58a143ac1f081e9065e3a27377e85e52726d4c92d3a235bd063a8b00777783
MD5 f58d612ecc371018188cec5d0a4467fc
BLAKE2b-256 566d719b999c72a32b8421812963ce925c6a20d2e90a948b0dbcede65b11545c

See more details on using hashes here.

File details

Details for the file aldakit-0.3.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.3.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a92a6b84140d6c74a581509f2660cbe40543359242923c728d69b6417761f517
MD5 2cbb4b9138427a8b4af27ed680d6f935
BLAKE2b-256 69d8fc99e2f921277822dd6847441897353133d45c14f7634e641d0b640d7ee9

See more details on using hashes here.

Release history Release notifications | RSS feed

0.4.0

26 files

This release

0.3.1 This release

26 files

0.2.1

26 files

0.2.0

26 files

0.1.10

26 files

0.1.9

26 files

0.1.8

26 files

0.1.7

26 files

0.1.6

31 files

0.1.5

26 files

0.1.4

6 files

0.1.3

6 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page