A Python library for symbolic music analysis, focusing on chord voicings and tensions.
Project description
PyVoicing
A Python library for symbolic music analysis, focusing on chord voicings and tensions, providing intuitive Python classes for working with pitches, chromas, intervals, and voicings.
- Pythonic syntax
- Lightweight, no dependency
PyVoicing is currently in Alpha stage. API and type hints are subject to change. Latest release: 0.1.4
Installation
pip install pyvoicing
Usage
from pyvoicing import Pitch, Chroma, Interval, Voicing
# shorthands
from pyvoicing import P, C, I, V
# or simply
from pyvoicing import *
# Pitch
middle_c = Pitch('C', 4)
middle_c.value # 60
~middle_c # 60, shorthand
middle_c.octave # 4
middle_c.offset # 0
middle_c.name # 'C'
middle_c.chroma # Chroma("C")
g = Pitch('G') # default octave=4
b = P('B') # shorthand P for Pitch
e = P('E5') # octave as part of the string
a = e >> 'P4' # transpose up a perfect 4th
a <<= 12 # transpose down an octave
# Voicing
Cmaj7 = Voicing([middle_c, g, b, e], root='C')
Cmaj7 # Voicing('C4 G4 B4 E5', 'C')
Cmaj7.tones # ['1', '5', 'maj7', 'maj3']
~Cmaj7 # [60, 67, 71, 76]
C69 = Cmaj7 + a - 'B4' + 'D5'
C69.tones # ['1', '5', '6', '9', 'maj3']
C69 >> 3 # Voicing('Eb4 Bb4 C5 F5 G5', 'Eb')
Bm7b5 = V('B D5 F5 A5', 'B') # shorthand
Bm7b5.tones # ['1', 'min3', 'b5', 'min7']
Bm7b5.root = 'G'
Bm7b5.tones # ['maj3', '5', 'dom7', '9']
G9 = V(Bm7b5)
C9 = G9 // 'C'
C9 # Voicing('E4 G4 Bb4 D5', 'C')
C913 = V(C9)
C913[1] >>= 'M2'
C913 # Voicing('E4 A4 Bb4 D5', 'C')
C913.tones # ['maj3', '13', 'dom7', '9']
C913.drop2 # Voicing('Bb3 E4 A4 D5', 'C')
C913.drop2.tones # ['dom7', 'maj3', '13', '9']
API Map (Quick Reference)
Pitch(value, octave=4): MIDI-backed pitch with properties likename,octave,offset,chroma,abc,lilypond,freq.Chroma(value): pitch class without octave; supports transposition with intervals.Interval(value, octave=0): interval distance withoffset,octave,interval.Voicing(pitches, root=None): collection of pitches with transposition, drop voicings, and chord-tone analysis viatones.Rest(): singleton rest placeholder.- Constants:
CHROMA_OF,ABC_OF,INTERVAL_OF,OFFSET_OF.
Operator Semantics (Proposed)
Keep operator meanings consistent and numeric-like; use named methods for collection or analysis.
# Pitch/Chroma transposition
Pitch("C4") >> "M2" # Pitch("D4")
Chroma("C") << "m2" # Chroma("B")
# Explicit named methods
Pitch("C4").transpose("M2") # Pitch("D4")
Pitch("C4").distance_to("E4") # Interval("M3")
# Spelling
from pyvoicing import Spelling
Spelling.prefer_flat = True
Pitch("C#4").spell() # "Db4"
Pitch("C#4").spell(False) # "C#4"
# Voicing composition
v = Voicing("C4 E4 G4", root="C")
v2 = v.add("B4")
v3 = v2.remove("E4")
v4 = v >> "M2"
Pitch
Pitch >> Interval -> Pitch(transpose up)Pitch << Interval -> Pitch(transpose down)pitch.distance_to(other) -> IntervalPitch == int|Pitchcompares MIDI values; string comparison is name-based unless it includes octaveSpelling.prefer_flat = Truecontrols default spelling;pitch.spell(prefer_flat=...)overrides oncepitch.lilyponduses LilyPond English note names (e.g.,cs,df)
Chroma
Chroma >> Interval -> ChromaChroma << Interval -> Chromachroma.distance_to(other) -> Interval(distance modulo 12)Spelling.prefer_flat = Truecontrols default spelling;chroma.spell(prefer_flat=...)overrides once
Interval
interval.add(other) -> Intervalinterval.subtract(other) -> Interval- Comparisons use semitone distance
Voicing
- Use named methods:
transpose(interval),transpose_down(interval),add(pitch),remove(pitch),find_interval(interval),to_root(target) - Avoid overloading
%and//for analysis/normalization ~voicingreturns MIDI values for all pitchesvoicing + pitchadds pitches;voicing - pitchremoves pitches
License
PyVoicing is licensed under the MIT License.
Contributing
Feature suggestions and bug reports are welcome!
Testing Matrix (Suggested)
- Parsing:
Pitch("C4"),Pitch("C#5"),Pitch("=C")(ABC),Chroma("Db"),Interval("M3"). - Transposition:
Pitch("C4") >> "M2",Chroma("C") << "m3",Voicing("C4 E4 G4") >> 12. - Equality:
Pitch("C4") == 60,Chroma("C") == Pitch("C5"),Voicing("C4 E4 G4") == Voicing("D4 F#4 A4") << "M2". - Notation:
Pitch("C4").abcoctave shifts, rest handling. - Regression: any reported bug gets a focused test.
Changelog
See CHANGELOG.md for version history and release notes.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyvoicing-0.1.4.tar.gz.
File metadata
- Download URL: pyvoicing-0.1.4.tar.gz
- Upload date:
- Size: 14.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6ef78b4b2296629a763508636cdff25eebfcd0a5518c6c222c9dae378e5d39d
|
|
| MD5 |
3e1f089185db8da39c290ba17049e02b
|
|
| BLAKE2b-256 |
efea9e392eece939dac0b556877cd1431acc92e1eb2190286bc6465181dbda97
|
File details
Details for the file pyvoicing-0.1.4-py3-none-any.whl.
File metadata
- Download URL: pyvoicing-0.1.4-py3-none-any.whl
- Upload date:
- Size: 14.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9136c31b3928d40283b828c6d88738c2e923bc7abe8fe9ce1304981e96678802
|
|
| MD5 |
6378c45b5c9e2052c2b293a2b1b403b0
|
|
| BLAKE2b-256 |
b015e9e6bd2c4a7a384ff9d1e8e02b34949fa07d7b389a52da9ce2865f70dd1e
|