Table of Contents

Python quickstart

Celeritas ships Python bindings that call the same native engine as the .NET API. There are two layers: a small, fast ctypes surface for the common operations, and a pythonnet escape hatch that exposes the entire engine.

The ctypes snippets below were run against the bindings; their printed outputs are real.

Install

# From this repository (editable install; the native library is bundled)
pip install -e ./bindings/python

# Or, once published to PyPI
pip install celeritas

Import the package:

import celeritas

The fast path (ctypes)

The top-level functions cover parsing, transposition, chord ID, key detection, chord-symbol parsing, and ornaments. Pitches are MIDI numbers (middle C = 60).

Parse a note

from celeritas import parse_note

note = parse_note("F#5")
print(note.pitch, note.duration)     # 78 0.25

note.time and note.duration are floats in whole-note units (a quarter is 0.25), matching the engine's time model.

Transpose (SIMD-accelerated)

from celeritas import transpose, midi_to_note_name

moved = transpose([60, 64, 67], 2)                 # up a whole step
print([midi_to_note_name(p) for p in moved])       # ['D4', 'F#4', 'A4']

transpose runs on the native SIMD path — it comfortably does millions of pitches per second.

Identify a chord

from celeritas import identify_chord

print(identify_chord([60, 64, 67]))        # CMajor
print(identify_chord([60, 64, 67, 71]))    # CMajor7

Prefer to think in note names? Build the pitch list from names with parse_note:

pitches = [parse_note(n).pitch for n in ["D4", "F4", "A4", "C5"]]
print(identify_chord(pitches))             # DMinor7

Detect a key

from celeritas import detect_key

key_name, is_major = detect_key([60, 62, 64, 65, 67, 69, 71])
print(key_name, "Major" if is_major else "Minor")   # C Major
Note

Key detection reports the pitch content's key. A natural-minor scale shares its notes with the relative major, so a bare A-minor scale reports as C Major — supply a tonic-weighted distribution (or use the full API's mode detection) when the distinction matters.

Parse a chord symbol

from celeritas import parse_chord_symbol

print(parse_chord_symbol("Cmaj7"))   # [60, 64, 67, 71]
print(parse_chord_symbol("C/E"))     # [52, 60, 67]  (slash chord: E in the bass)

Spelling

from celeritas import midi_to_note_name

print(midi_to_note_name(66))                     # F#4  (sharps by default)
print(midi_to_note_name(66, prefer_flats=True))  # Gb4

Ornaments

from celeritas import parse_note, Trill, Mordent, MordentType

note = parse_note("E4")
trill = Trill(note, interval=2, speed=8)
print(len(trill.expand()))                       # 8 notes

mordent = Mordent(note, mordent_type=MordentType.UPPER, alternations=1)
print([n.pitch for n in mordent.expand()])       # [64, 66, 64]

The full API (pythonnet)

The ctypes surface is a focused subset. To reach everything — the progression advisor, voice-leading solver, modal analysis, MIDI I/O, and the rest — load the managed .NET assembly through pythonnet:

pip install pythonnet
# Build the managed assembly (Release recommended); the loader searches for it,
# or point CELERITAS_DOTNET_ASSEMBLY at Celeritas.dll explicitly.
dotnet build src/Celeritas/Celeritas.csproj -c Release
from celeritas import load_celeritas, is_pythonnet_available

if is_pythonnet_available():
    Celeritas = load_celeritas().namespace     # the .NET Celeritas namespace
    Analysis = Celeritas.Core.Analysis

    report = Analysis.ProgressionAdvisor.Analyze(["Dm7", "G7", "Cmaj7"])
    print(report.Key, report.Pattern)
    for c in report.Chords:
        print(c.Symbol, c.RomanNumeral, c.Nashville)

Through this path you call the public .NET types directly, so the API reference is your guide — the C# signatures apply verbatim.

See also