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.4.0.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.4.0-cp314-cp314-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.14Windows x86-64

aldakit-0.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (922.4 kB view details)

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

aldakit-0.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (910.3 kB view details)

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

aldakit-0.4.0-cp314-cp314-macosx_11_0_x86_64.whl (859.0 kB view details)

Uploaded CPython 3.14macOS 11.0+ x86-64

aldakit-0.4.0-cp314-cp314-macosx_11_0_arm64.whl (835.9 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

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

Uploaded CPython 3.13Windows x86-64

aldakit-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (922.5 kB view details)

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

aldakit-0.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (910.0 kB view details)

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

aldakit-0.4.0-cp313-cp313-macosx_11_0_x86_64.whl (858.8 kB view details)

Uploaded CPython 3.13macOS 11.0+ x86-64

aldakit-0.4.0-cp313-cp313-macosx_11_0_arm64.whl (835.7 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.12Windows x86-64

aldakit-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (922.6 kB view details)

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

aldakit-0.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (910.3 kB view details)

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

aldakit-0.4.0-cp312-cp312-macosx_11_0_x86_64.whl (859.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ x86-64

aldakit-0.4.0-cp312-cp312-macosx_11_0_arm64.whl (835.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

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

Uploaded CPython 3.11Windows x86-64

aldakit-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (924.8 kB view details)

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

aldakit-0.4.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (912.5 kB view details)

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

aldakit-0.4.0-cp311-cp311-macosx_11_0_x86_64.whl (860.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ x86-64

aldakit-0.4.0-cp311-cp311-macosx_11_0_arm64.whl (837.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

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

Uploaded CPython 3.10Windows x86-64

aldakit-0.4.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (925.2 kB view details)

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

aldakit-0.4.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (912.8 kB view details)

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

aldakit-0.4.0-cp310-cp310-macosx_11_0_x86_64.whl (860.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ x86-64

aldakit-0.4.0-cp310-cp310-macosx_11_0_arm64.whl (838.2 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: aldakit-0.4.0.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.4.0.tar.gz
Algorithm Hash digest
SHA256 e9d14456021c345809d3de83e6ec38fb0e5f8dfad61c64e695a19f75428add17
MD5 5bbc8689e381fb558f60b1bd3ed1167d
BLAKE2b-256 4a5c8f26590c1bc1808a06894777ad10448dc6ba35691939d43281b6c90a6934

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.4.0-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.4.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 7ae5c001c760b6110958f7e71572a009721d4e38c7648850818e7c66ffc67f9d
MD5 ed2e7ceeb18cd160828d9bbe7980e952
BLAKE2b-256 5e608680053ae2af3708127697bf4fc92ec65ac0d7f343c214115553ed3b41d1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d3276598d842697baa9fa896713e06a425b052d2bb2ba20f9b93b863168ecf55
MD5 e5a5557dab176cfb1c5795fa7690d4e6
BLAKE2b-256 733b0315441d695469fa7a45d0be4a81e226b072e5dc664157beceb9f9baad21

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8e2f74be4eeabe83a8b0ef0b6419a34c60db994bb59f33aff5b62f1d9f5bfe9e
MD5 8ef8d4bfcc1796a24d448bba09ec6abd
BLAKE2b-256 fc93def59597271175350bb8022d206535270ccfc23ee2f251251da958e1f203

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp314-cp314-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 5e8bfd463e62b288c57b9440b3971ac565aedeb9d169e87c115dccb8b9d3f2f9
MD5 97cfaab8ec6cf2b094f518e6acb2aa9f
BLAKE2b-256 dc933aca7466cd1a6dc8dfb2b8c036afe770374b2aa57c474230646cc28be8cd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 87fa750d58bacb19e808e409631fb3f141871b9b9f9863791346d86da90b8aad
MD5 41bb3299a0360f927103660897e822c2
BLAKE2b-256 681bbe55385548d0fd39561cbcb923f9505765fed48ed181690e08b48597b964

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.4.0-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.4.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 a972e8a8b870fbabe33792b9a2b36e588fdcf60e535cba0773bfa3569439ec22
MD5 a57c3061f77087ef982613e06939b92e
BLAKE2b-256 759a58ba4ab6994c044561f9e0507e42dd494c045e68ed9e79afdc0554b0df45

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 96879eeb61a3366104ddac397c094e0a04e17034e138e3a7fbce35b8febcc29b
MD5 e5b0e8611d61e7f6be5dbf772576cc0e
BLAKE2b-256 bab8880d8b7fea5280e84fe0fd7d151489d1fb897be2acd5fd27dfa435f434df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 13dff0c077ee56abc090ac3863ba619ec27d9e31a4762472abb4d697d08558e8
MD5 d5a416b681a1edc3cb9535f1214773e8
BLAKE2b-256 dbc9fd9a862eada5e7bbb1f15c3db5b16e688b9de79746800df61d5b603a3d0a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp313-cp313-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 fe120cd474e2ef10b2ebc63112172e87ec346214715c2a4f0aa07d8c362f7a7f
MD5 3b2a9a5807d8964406dc376adb0fc927
BLAKE2b-256 b159b0a09538c8b31c5a5286bec12d35f2322aeaec496feb328a3668df61e538

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1793aa954e80f2861d2fc3c6dedcc8076897889973c831a99b877fdd72e9d7c0
MD5 8ee9baeed5dd881a8e3efca7345e42c1
BLAKE2b-256 64672bae16776908242f23466209573a09ea81a3aa1f4f41c6d8f8310b34abb7

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.4.0-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.4.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 0aa10df27b6fe38258da8e0420296f573f1dc29f9c8d1264528519fd17b54077
MD5 59fc68278caae6535a4f26b37a10bbca
BLAKE2b-256 2828c845024b398a62c3bd975f735c22b29c01392a43af7aecdef8f2b0af0572

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 74e5dcf65f2a12c1bf3354f7ca0afd1e0cb5f7c0807aea56c90f7810f47aa5a1
MD5 3c27dd167fdb96d8c939c942115af8fa
BLAKE2b-256 20515dc67fad0483f7172841d5a8a7f90ec6cec601ec77167f6a3d1f14c73d38

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 77035cfddb55a77a06c54e43605da5656114720f3f39daf25e9a4bb96e6858c6
MD5 1e98ea9e3efd9731b7d4d4f68bd6cb2a
BLAKE2b-256 4427a5bd879c30d695ad433cf70f1ebbad4229f503e77c4b3953736083f8fc6c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp312-cp312-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 05ee0f467e670dab42c359e0dd76abae39069e38a1e7f1d778a67ac3192c34da
MD5 9905cafa291242d2b03f03f476f76e27
BLAKE2b-256 fd55b0b5a626a0ec91555ec2531abe6aa4e442e71fde2aa1f21a6c00bad5ddde

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9590bd1711d23ea473f5dfb41b75a33c177c5fe60a7938c5e6e0f32aa6e74fac
MD5 2708ec82044fb29491a8af06f1c717a1
BLAKE2b-256 77577e34f9ab5bbcd112926192b157519c73bb40323cb79f8aab65b5526c0480

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.4.0-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.4.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 c8b39c7fd4735b8c17757e90f731cde3bd9f0a7e0b0255c0c8eef1ac77361102
MD5 606b1275a63e25d0d248129c04f6c684
BLAKE2b-256 b10cb2fa6fa342a3edd0833a40ac74f0a4516966cd1b20660510a99aabb56608

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bd58a9286c8bfc79878b665c1ad9ddae48c8f6285b334474bfbaa44f2236b0ed
MD5 d5e684637a7dc03e396a3b6c4925ae25
BLAKE2b-256 e7e8ad8a4d89b794d2afd480f48fca5686839168a9e2e99f37ba9b77e2917bae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 289d21539d66efe7642424b42be82da23e79b6e76e16ef84bcc45439b7a820bd
MD5 a5b76f26c8bc9bcfe295c5dbf233e997
BLAKE2b-256 4af1ca9994bdd19d06ab4e0ed3847989db75ccd3bde44b6349f38e50a2e97ae2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 fa363c666236a1f3acc90221bfc927f15daa61f68299fc16e44800b9f2e33369
MD5 304150b67c68056dc911849fe0e7da09
BLAKE2b-256 9c1b28b3833d07202b8fe66fcabe9cf2082c7cd5be548d79f88c918354c8d6c6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bd69905ddc76878b2da5695e91988e4e8b1b470f50d2b7010565cd2004bcc030
MD5 de7f66dd82ae7f9c080fc7c463d1afa6
BLAKE2b-256 9d1568024a40de5bdfde774e79cea3061b63b761c03b529840f3804af040b44e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.4.0-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.4.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 b01b17db364a70d8edb56fa7cc72998b7915128e3caa225ac47e97d006770349
MD5 f2580813c6b96df94055ee8030736f0e
BLAKE2b-256 8a27d235a9ab25b6b8ce782bcbe2e68b1b52a387ded861fb59725e72cd935797

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d31fbe9f8fb867dff6d874e2f00d30e8f1b1633ce746a61ed753e3c578ab2abf
MD5 333062a807c0f835c4f03e6e125e3c56
BLAKE2b-256 8cc3029b9956fd4e74568eda24579cb74959fbc0fc245c7959cd4ec81e32e1c4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a042f413dfeadd9ef6d5cd5c2d9058abef076abf25d05f28d53fb46ac5abc900
MD5 20433d4f585511cab7d9f2c019e77bb5
BLAKE2b-256 7bfadda0f61a5a22719cf51bf79a3abcc64a81657d29a542f8e07bc90905c4b3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp310-cp310-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 bfaaf4dc925e7ef258c8a547e57a824561f1c3387b533033d6363edbe05e85ac
MD5 4ff7656b433a48274c4ec5434e7de316
BLAKE2b-256 4446417bea633d47cf3d0b9b8900d6ffceb8d5e1ea09a9b08727f4a8a7f550cf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.4.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f68453ae4900bc844c64be705b1d70666aaccb1525f7e4a42711b9038d1cdce4
MD5 4ab7be4f33861cabd3dd91d34b48735d
BLAKE2b-256 a7dcfd06f17186213709356adf2819007a02f0f7ae85c011b2d85e42547f4779

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.4.0 This release

26 files

0.3.1

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