accompy.converters

Core types for the chord-to-audio pipeline.

Defines the data types that flow through the pipeline, plus a converter registry that maps (source_type, target_type) pairs to converter functions.

The key types form a DAG:

ChordSheet --> ChordSequence --> NoteSequence --> MidiData --> AudioData

(Plus shortcut converters that skip intermediate steps.)

Usage:

>>> from accompy.wips.types import converter, ChordSequence, MidiData
>>> # Get a specific converter
>>> to_midi = converter[ChordSequence, MidiData]
>>> # Or convert in one call
>>> midi = convert(chord_seq, MidiData)
class accompy.converters.AudioData(waveform: ndarray, sr: int = 44100)[source]

Container for audio data — numpy array + sample rate.

>>> import numpy as np
>>> ad = AudioData(waveform=np.zeros(44100), sr=44100)
>>> ad.duration_seconds
1.0
to_wav_bytes() bytes[source]

Convert to WAV file bytes.

write(path: str) str[source]

Write audio to a WAV file. Returns the path.

class accompy.converters.ChordSequence(chords: list[tuple[str, float]], title: str = '', key: str = 'C', tempo: int = 120, time_signature: tuple[int, int] = (4, 4))[source]

Ordered sequence of (chord_symbol, duration_beats) pairs with metadata.

This is the canonical internal representation of a chord progression.

>>> cs = ChordSequence([("Dm7", 4.0), ("G7", 4.0), ("Cmaj7", 8.0)])
>>> len(cs)
3
>>> cs[0]
('Dm7', 4.0)
>>> cs.total_beats
16.0
property durations: list[float]

Just the durations, without symbols.

property symbols: list[str]

Just the chord symbols, without durations.

to_score()[source]

Convert to an accompy Score for pattern-based accompaniment.

Example

>>> cs = ChordSequence([("Dm7", 4.0), ("G7", 4.0)])
>>> score = cs.to_score()
>>> len(score)
2
class accompy.converters.ConverterRegistry[source]

Registry mapping (source_type, target_type) to named converter functions.

Supports multiple converters for the same type pair, distinguished by name. The first registered converter becomes the default.

>>> reg = ConverterRegistry()
>>> reg.register(str, int, int, name='builtin')
>>> reg[str, int]('42')
42
>>> reg.list_converters(str, int)
['builtin']
get(source_type: type, target_type: type, name: str | None = None) Callable[source]

Get a specific named converter, or the default if name is None.

list_converters(source_type: type, target_type: type) list[str][source]

List available converter names for a type pair.

list_pairs() list[tuple[str, str]][source]

List all registered (source, target) type name pairs.

register(source_type: type, target_type: type, func: Callable, *, name: str = '', is_default: bool = False) None[source]

Register a converter function.

Parameters:
  • source_type – The input type

  • target_type – The output type

  • func – The converter function (source -> target)

  • name – Name for this converter (defaults to func.__name__)

  • is_default – If True, make this the default converter for this pair

set_default(source_type: type, target_type: type, name: str) None[source]

Change the default converter for a type pair.

class accompy.converters.MidiData(bytes_: bytes | None = None, pretty_midi_obj: Any = None, tempo: int = 120, time_signature: tuple[int, int] = (4, 4))[source]

Container for MIDI data — either as bytes or as a pretty_midi object.

Wraps MIDI content so converters have a uniform interface regardless of which MIDI library produced the data.

>>> import io
>>> md = MidiData(bytes_=b'MThd...', tempo=120)
>>> md.has_bytes
True
to_bytes() bytes[source]

Get MIDI as bytes, converting from pretty_midi if needed.

to_pretty_midi()[source]

Get as pretty_midi.PrettyMIDI, converting from bytes if needed.

write(path: str) str[source]

Write MIDI to a file. Returns the path.

class accompy.converters.NoteSequence(notes: list[tuple[list[int], float]], tempo: int = 120, time_signature: tuple[int, int] = (4, 4))[source]

Ordered sequence of (midi_notes, duration_beats) with metadata.

Represents resolved chords — chord symbols have been converted to concrete MIDI note numbers.

>>> ns = NoteSequence([([60, 64, 67], 4.0), ([62, 65, 69], 4.0)])
>>> ns[0]
([60, 64, 67], 4.0)
accompy.converters.convert(source: Any, target_type: type, *, via: str | None = None) Any[source]

Convert source to target_type using the registered converter.

Parameters:
  • source – The source data

  • target_type – The desired output type

  • via – Optional converter name (uses default if None)

Returns:

Converted data of target_type

Example:

>>> # After converters are registered:
>>> # audio = convert(chord_seq, AudioData)