Voice¶
- class paeonia.Voice(bars=None, *, default_tonality=None, tonality_plan=None, name=None)[source]¶
Bases:
objectAn ordered collection of bars forming one musical part.
A voice owns its bar list but does not copy the individual, mutable
Barobjects. Its default tonality provides a fallback tonal context, while aTonalityPlancan override that context at selected bar indices. These tonal fields are metadata; construction does not alter pitches or bar-level tonalities.- Parameters:
bars (Iterable[Bar] | None) – Initial bars. The iterable is materialized into a fresh list.
default_tonality (Tonality | None) – Fallback tonal context for bars without a more specific assignment.
tonality_plan (TonalityPlan | Mapping[int, Tonality] | None) – Tonality changes keyed by zero-based bar index. Mappings are converted to an immutable
TonalityPlan.name (str | None) – Optional display name for the voice.
- Raises:
TypeError – If a bar, tonality, plan, plan value, or name has the wrong type.
ValueError – If the tonality plan contains an invalid bar index.
- tonality_at(bar_index, *, inherited=None, inherited_plan=None)[source]¶
Resolve the effective tonality at a bar index.
Resolution proceeds from the most local context to the least local: a bar override, the voice’s tonal plan, its default tonality, an inherited plan, and finally the inherited default. Plan changes remain active after their change index.
- Parameters:
bar_index (int) – Zero-based index of a bar in this voice.
inherited (Tonality | None) – Default tonality inherited from a containing score.
inherited_plan (TonalityPlan | None) – Score-level tonal changes indexed by bar position.
- Returns:
Resolved tonality, or
Noneif no level defines one.- Return type:
Tonality | None
- Raises:
TypeError – If an index or inherited tonal context has the wrong type.
IndexError – If
bar_indexdoes not identify a bar in this voice.
- apply_tonality(target, source=None, *, inherited=None, inherited_plan=None, chromatic='preserve_alteration', degree_policy='error')[source]¶
Reinterpret every bar in a single target tonality.
Source tonalities are resolved independently for each bar. An explicit
sourceargument has highest priority, followed by the bar’s own tonality, this voice’s plan, this voice’s default tonality, an inherited plan, and finally the inherited fallback. Plan changes persist from their change index onward according toTonalityPlan.at().The operation is immutable. Each transformed bar has its tonality cleared because the returned voice stores
targetas its default tonality. The returned voice also has an empty tonality plan and keeps this voice’s name. Pitches, rests, chords, durations, velocity, and tie metadata otherwise followBar.apply_tonality().- Parameters:
target (Tonality) – Tonality in which every transformed pitch is realized.
source (Tonality | None) – Optional source tonality forced across every bar. When omitted, the per-bar precedence chain described above is used.
inherited (Tonality | None) – Lowest-priority tonal context inherited from a containing object.
inherited_plan (TonalityPlan | None) – Inherited tonal changes indexed by this voice’s bar positions.
chromatic (str) – Chromatic analysis policy passed to
Bar.apply_tonality():"preserve_alteration","error", or"nearest".degree_policy (str) – Policy for differing source and target degree counts, passed to
Bar.apply_tonality():"error"or"wrap".
- Returns:
A new voice expressed in
target.- Return type:
- Raises:
TypeError – If a supplied tonal context or plan has the wrong type.
ValueError – If a policy is unknown, no source tonality can be resolved for a bar, or a bar cannot be mapped under the selected policies.
- span()[source]¶
Return the voice’s total duration in whole-note units.
The result is the sum of every bar’s span. Rests contribute their durations like pitched notes, and an empty voice has a span of zero.
- Returns:
Exact total duration across all bars.
- Return type:
Fraction
- bar_spans()[source]¶
Return each bar’s duration in voice order.
Empty bars contribute
Fraction(0). An empty voice therefore returns an empty tuple.- Returns:
Exact duration of each bar in whole-note units.
- Return type:
tuple[Fraction, …]
- add_bar(bar)[source]¶
Add a new bar to this voice.
- Parameters:
bar (Bar) – A Bar object
- Return type:
None
- fill(notes)[source]¶
Replace this voice’s bars with events from
notes.Existing bars provide the finite rhythmic structure and explicit bar tonalities. Events are consumed in order, split and tied where they cross bar boundaries, and consecutive rests are combined within each bar. The voice’s default tonality, tonal plan, and name are unchanged.
The operation mutates this voice by replacing its bar entries, but it does not mutate any existing
Bar. Retaining the underlying bar sequence also allows a voice obtained from a score slice to update the corresponding bars in the original score. Filling is atomic: if event validation or exhaustion fails, this voice remains unchanged.- Parameters:
notes (Iterable[Note]) – Finite or infinite source of notes, chords, and rests.
- Returns:
This modified voice, allowing method chaining.
- Return type:
- Raises:
TypeError – If the source produces an object that is not a note.
ValueError – If the source ends before all existing bars are filled.
- to_midi(tpb=480)[source]¶
Return MIDI messages for the complete voice.
Conversion is delegated to
midi.voice_to_midi_messages(). That renderer is responsible for carrying the playback offset from one bar to the next so events remain correctly ordered across bar boundaries.- Parameters:
tpb (int, default=480) – MIDI ticks per beat.
- Returns:
MIDI messages emitted by the voice renderer.
- Return type:
list
- to_lilypond(*, inherited=None, inherited_plan=None)[source]¶
Return LilyPond notation for the voice in its score context.
Rendering is delegated to
lilypond.voice_to_lilypond(). The renderer walks bars in order, resolves the effective tonality at each bar using the voice and inherited score contexts, and emits a key signature only when that resolved tonality changes.- Parameters:
inherited (Tonality | None) – Default tonality inherited from the containing score.
inherited_plan (TonalityPlan | None) – Score-level tonal changes indexed by bar position.
- Returns:
LilyPond notation emitted by the voice renderer.
- Return type:
str
- show()[source]¶
Render and display this voice, then return it.
Display is delegated to
playback.show_voice(). Returning the voice supports fluent use in notebooks.- Returns:
This voice, unchanged.
- Return type:
- play(tpb=480, autoplay=False)[source]¶
Render and play this voice, then return it.
Playback is delegated to
playback.play_voice().- Parameters:
tpb (int, default=480) – MIDI ticks per beat.
autoplay (bool, default=False) – Whether the playback helper should start playback immediately.
- Returns:
This voice, unchanged.
- Return type: