Skip to main content

Python parser and MIDI generator for the Alda music programming language

Project description

aldakit

PyPI version Python 3.10+ License: MIT

A zero-dependency Python parser and MIDI generator for the Alda music programming language[^1].

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

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
  • MIDI Import - Load MIDI files and convert to Alda notation
  • 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
  • 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

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")

# 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 with options
score.play(port="FluidSynth", wait=False)

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

# 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)
  • Tempo detection and preservation
  • General MIDI instrument mapping
  • 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()

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_vel=50, end_vel=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,ports,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
ports List available MIDI ports (both input and output)
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] [-o FILE] [--port NAME|INDEX] [-sf FILE] [--stdin] [--parse-only] [--no-wait] FILE
Option Description
FILE Alda file to play (use - for stdin)
-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
--stdin Read from stdin (blank line to play)
--parse-only Print AST without playing
--no-wait Don't wait for playback to finish

eval Subcommand

aldakit eval [-v] [-o FILE] [--port NAME|INDEX] [-sf FILE] CODE
Option Description
CODE Alda code to evaluate
-v, --verbose Verbose output
-o, --output FILE Save to MIDI file instead of playing
--port NAME|INDEX MIDI port by name or index
-sf, --soundfont FILE Use TinySoundFont audio backend

repl Subcommand

aldakit repl [-v] [--port NAME|INDEX] [-sf FILE] [--sequential]
Option Description
-v, --verbose Verbose output
--port NAME|INDEX MIDI port by name or index
-sf, --soundfont FILE Use TinySoundFont audio backend
--sequential Start in sequential mode (wait for each input)

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 (used as fallback when no MIDI ports available)
backend string midi Default backend: midi or audio
port string none Default MIDI output port name
tempo integer 120 Default tempo for REPL (BPM)
verbose boolean false Enable verbose output

Backend Selection Priority

  1. CLI -sf /path/to/soundfont.sf2 forces audio backend
  2. Config backend = audio forces audio backend
  3. If MIDI ports are available, use MIDI (default)
  4. If no MIDI ports available and soundfont is configured, fall back to audio
  5. If no MIDI ports and no soundfont configured, show error

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:

  • :help - Show help
  • :quit - Exit REPL
  • :ports - List MIDI ports
  • :instruments - List available instruments
  • :tempo [BPM] - Show/set default tempo
  • :stop - Stop playback

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 ~/Music/sf2/:

Option 2: Auto-download

from aldakit.midi.soundfont import setup_soundfont

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

Option 3: 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 --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 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

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

Project details


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.1.8.tar.gz (2.0 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.1.8-cp314-cp314-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.14Windows x86-64

aldakit-0.1.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (837.2 kB view details)

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

aldakit-0.1.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (825.4 kB view details)

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

aldakit-0.1.8-cp314-cp314-macosx_11_0_x86_64.whl (765.7 kB view details)

Uploaded CPython 3.14macOS 11.0+ x86-64

aldakit-0.1.8-cp314-cp314-macosx_11_0_arm64.whl (753.8 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

aldakit-0.1.8-cp313-cp313-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.13Windows x86-64

aldakit-0.1.8-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (837.2 kB view details)

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

aldakit-0.1.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (825.1 kB view details)

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

aldakit-0.1.8-cp313-cp313-macosx_11_0_x86_64.whl (765.7 kB view details)

Uploaded CPython 3.13macOS 11.0+ x86-64

aldakit-0.1.8-cp313-cp313-macosx_11_0_arm64.whl (753.6 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

aldakit-0.1.8-cp312-cp312-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.12Windows x86-64

aldakit-0.1.8-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (837.3 kB view details)

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

aldakit-0.1.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (825.3 kB view details)

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

aldakit-0.1.8-cp312-cp312-macosx_11_0_x86_64.whl (765.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ x86-64

aldakit-0.1.8-cp312-cp312-macosx_11_0_arm64.whl (753.7 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

aldakit-0.1.8-cp311-cp311-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.11Windows x86-64

aldakit-0.1.8-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (839.4 kB view details)

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

aldakit-0.1.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (827.5 kB view details)

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

aldakit-0.1.8-cp311-cp311-macosx_11_0_x86_64.whl (767.0 kB view details)

Uploaded CPython 3.11macOS 11.0+ x86-64

aldakit-0.1.8-cp311-cp311-macosx_11_0_arm64.whl (755.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

aldakit-0.1.8-cp310-cp310-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.10Windows x86-64

aldakit-0.1.8-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (839.9 kB view details)

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

aldakit-0.1.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (827.8 kB view details)

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

aldakit-0.1.8-cp310-cp310-macosx_11_0_x86_64.whl (767.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ x86-64

aldakit-0.1.8-cp310-cp310-macosx_11_0_arm64.whl (756.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for aldakit-0.1.8.tar.gz
Algorithm Hash digest
SHA256 a5302f209602cf6658b654ac6379b446aab78844f6edce5ecac7f2b4fbad5063
MD5 db4361d2b8328af80fb43f93793a01e1
BLAKE2b-256 028bfa14d019b60946d99465211208ebdb49dbdc6c04b74c6475a322de75216d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.1.8-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 1.1 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.1.8-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 e7061966896f4a17216f3b2aff82be387f739806b6bb432d9c5a71368d3a30bf
MD5 18845c27db323d44007c63fe16551131
BLAKE2b-256 52277feb0058b722c539a9a71ef49629127b4323fa518d7d3012ca3b969275c0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 860cdf40757c51f0e7812aa6563121525afae85ab3d0053998c2817641c8cc4d
MD5 6e33848a378b7fbc872e93b9dbaad5b4
BLAKE2b-256 dc977b7a84393671b3c7773100ec981412d9613602c054e1ac5337114cb213fa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6cac94ac7974b68c777b77cb0f5be140485728413e68f9a9a30e46ebe57742de
MD5 4701a47207eb6238eb0a764de1e121e6
BLAKE2b-256 10f55cce695d601f42d8c24e5bb2f82bb1c2990611c52605139151319c7f42b7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp314-cp314-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 46282f7cbca18bd70f1322486e674aa3faf219493e8c015fb4bb1c08fe098ea6
MD5 078cf9c6fc07e87128b09d9c4a030990
BLAKE2b-256 23b9668adabced37fa0eed7e0bfe245f5193e0f49f062b6927643a014f0d64b7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 669706e184f391c6446195ce9d84c375900791855828d39d50f70cc27c8b3da3
MD5 12438d650707364b88d0fbd7959b4369
BLAKE2b-256 011d985a6865a684c0ef82234027e4c0810cae2bae34975376703e7f0f365d66

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.1.8-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 1.1 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.1.8-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 f8dba7d3557be5e51e0fb4532781dc8a8f617b4ca2e0e90eac87dc502af77659
MD5 4ffadc42b9540d28200b517b87f748a0
BLAKE2b-256 c7922c4180865425829f15eb81d5f201bd841d3f33da9a962d29e153afe15076

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 df02952aeedcbb1530c2fc7914c638dcb097ae4a8df72b0c3eb384d692a19ebc
MD5 e8d1353fffdd5736ba5e47f7297fe804
BLAKE2b-256 0110294d3eebee750e8116037982cf816b9aeccb9f27f6048eebdfdb92534c9e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7ff909546b469b32ecede36dec3ae91b666425e3cc2649fdf90e58173de1bade
MD5 a7d2d13d80345abecc92c72776e08e77
BLAKE2b-256 e9f5b05e8020af1961fdf5801512568b57dd4aa59d090065b68ea4202e549cb8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp313-cp313-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 75c6638923ba68649246a38c5dc91657fccab5dd93f693dd21c63cf7935f2788
MD5 3aa939601cdf3d0edc6cb5c950bcbc4c
BLAKE2b-256 d9df363ec013ae45bfc4a5bcdd3793860ddd55b2abbeeea2b7dbb3f7d285a549

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8b50484f378bb33ecdc1e2c4142b086f2f4eb19f675d4c1d421f87246f129b2b
MD5 544cae5cbac53e2a36f6a8e9e6e40781
BLAKE2b-256 49bd8499865ce59666a1decd524d1280dc7375060bca45ca65298118dfd76416

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.1.8-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 1.1 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.1.8-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 a5adcd0850a0687d6dc22a295a43a07b8e77b8833f678b00fc4db454b83227bd
MD5 0a4d5a23025ab03957c6d891ccc67388
BLAKE2b-256 708d1f2a190202beda6d275105ae302f778f6f9b64ce3377e8c97783b9098b59

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f101c75d990db62775700fa71ef04fcae451fd7e6b4d1bb48fd157c8c97b61d4
MD5 e911af7d2349b5a779be107ebca9567b
BLAKE2b-256 6bf1eb8e5d04cf024b4a0376896f72f712b4ef9cf8c59e7559aadd316da8d47c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3c6f3cb4263cc9b69c5a5ea7edd8e346a9ca6ecb4bf9112b042ee6931fb1d67e
MD5 8e4d13e00c0d84a25f968b5f771e9e4c
BLAKE2b-256 2cc0c9c5fb3e06bb0fd59d038c281c859b9f262b5559d39fd6510d37424b6a6b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp312-cp312-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 e65ca19ef08fb21ac37389d35229ae293d5c2e40b25cf04acb00958090040c96
MD5 39d992487ba1fa08e203cda52b5f87fd
BLAKE2b-256 d30905164835abfcaae875e40db9a1ec4f6373961e9fd4d6ceb03dd8848c2c5b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bebeaa8269b8615061ee96356f1a37e2ee019bfe09eff324a9ac6eb347b6a627
MD5 427fad42067375b98a79da9f99b7f902
BLAKE2b-256 a8d898e9920071ca7624bb197c07ce4e3ba7906ee8cf5044a245a48bfe597171

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.1.8-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 1.1 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.1.8-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 40550a2e0a8ce5c23819d43d44625204df2c494f9ef8ab01c2c35d8d21666814
MD5 fd91ddd054d1580c3c6f23ebe55146f7
BLAKE2b-256 d6e1cf800e5d117ac1b33892eb0efd397675ca1434f364ae814adca14b3fafd5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7be2031e620267380ce9b77cf50eed453b06c6554538c30edf7eefefb6d1bb82
MD5 fac4ea2db97a4f6a4caf283f5cde5aba
BLAKE2b-256 1dc69fc30711696223c59bcc6a0b00b80c6e11a07d33c53f5d781d268dfb0390

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d852cc769db52b3b8138da1e2d491cc8718f4d12c07d403186270088bcf5fce8
MD5 41b9404e947c746b4d74cf23d06bb5a3
BLAKE2b-256 04768e47405fb2bcdec5dcf2b1db707da859542d09075f1f7f4569876fa6b669

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 732b00bb807ce8adc11009c1e369dbb830a5fa215985e06e17b3e00c07126618
MD5 23c58b4925f1d3b3bf38d826ad6280b9
BLAKE2b-256 39dbce69a8e13269bec9609afd005ba1ea57c7dc670598f22b9b62c04ac5f3bd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e72700fd35e607c0b1f9363935e2e5a3cac4e8fc18086d35a82ddcdfe4ac4755
MD5 132c041f85730c7e5f8c9b62f2e473d4
BLAKE2b-256 8cfeb341700e7a8b0e1a2aa59fbb5e6b3aa38e2353934869f1e2acd0e5407980

See more details on using hashes here.

File details

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

File metadata

  • Download URL: aldakit-0.1.8-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 1.1 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.1.8-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 b97419f6032c4e30e3c103be536bc319936e05897d5615c6aee9a5a5f43d6fa2
MD5 81604a09d75f666141a14fda293379d3
BLAKE2b-256 0d013904b4cd67f7d231020a51a06393cd3acd0b4c57032c0ce28bce9bd8b34a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 01283563389abf687c193351d55c9e2efb25fbc2fe45010e86534c89da6e857f
MD5 5f5cebe2c0e54b0c61fc58a2fb9722d7
BLAKE2b-256 c5a16363f44f6ff0cb0deed8da4e4374681ec9067793f57990956bbec6e5ba53

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 761bc9f82df5ceca584d0acab8908716169990b08a6ca46ad67d41acb233e44f
MD5 74633595289f663368315435f78f33c6
BLAKE2b-256 463a520dd405a7ada66414f38fc7f2e59c03fbf8a8d1cd45bc037d363537bd85

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp310-cp310-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 f36a7e3919689dbd9a0de0ec9c7e09655a52231ee4b13de39285ee1a909875a9
MD5 e7da6e61dbc4f20c8338e1e64a069197
BLAKE2b-256 bd8a938dc71bab3eb2c5f534fa862eddfcf81f6d72e286d02197aaec2416dd9e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aldakit-0.1.8-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 15a2499823ddc508b1f54f7e94b8ff710b40d2100768cffb1c34f3e4d06c4b60
MD5 3a7aa69140d6dbdcc811463fd8ddf5dc
BLAKE2b-256 3504e9833055795a9bfbfa6f30a8e37c42c51b4c06b7a5ced5c2032427f793fd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page