@@ -80,6 +80,15 @@ def parse_abc_notation(abc_string: str, default_octave: int = 4) -> Tuple[dict,
8080 metadata ["composer" ] = line [2 :].strip ()
8181 elif line .startswith ("R:" ):
8282 metadata ["rhythm" ] = line [2 :].strip ()
83+ elif line .startswith ("%%transpose" ):
84+ # Handle transpose directive if needed
85+ matched = re .match (r"%%transpose\s+(-?\d+)" , line )
86+ if matched :
87+ # only octave transposition is supported
88+ octaves = int (matched .group (1 )) / 12
89+ if octaves + default_octave < 0 :
90+ octaves = 0
91+ metadata ["transpose" ] = int (octaves )
8392 elif not line .startswith ("%" ) and line :
8493 music_lines .append (line )
8594
@@ -126,6 +135,8 @@ def parse_abc_notation(abc_string: str, default_octave: int = 4) -> Tuple[dict,
126135 logger .info (f"Playing: { metadata ['title' ]} " )
127136 logger .info (f"BPM: { bpm } , Beat Unit Fraction: { beat_unit_fraction :.3f} , Default L: { default_unit_fraction :.3f} " )
128137 logger .info (f"Duration of 1 beat: { duration_of_beat_unit :.3f} s. Default L: Duration: { default_duration_in_seconds :.3f} s" )
138+ if "transpose" in metadata :
139+ logger .info (f"Transposing by { metadata ['transpose' ]} octaves. Target default octave: { default_octave + metadata ['transpose' ]} " )
129140
130141 # --- 5. Parse Music Lines ---
131142 music_string = " " .join (music_lines )
@@ -151,6 +162,8 @@ def parse_abc_notation(abc_string: str, default_octave: int = 4) -> Tuple[dict,
151162 rest = token [1 :]
152163
153164 octave = default_octave
165+ if "transpose" in metadata :
166+ octave += metadata ["transpose" ]
154167 if note_char .islower ():
155168 octave = octave + 1
156169 note_char = note_char .upper ()
0 commit comments