opmo Posted January 24 Posted January 24 After receiving some feedback on the new function, I decided to expand its functionality further. I hope it will become a useful tool in various contexts of your composition. Update 3.0.29556 split-chord (chord-span sequence &key lower-size upper-size lower-ambitus upper-ambitus lower-transposition upper-transposition lower-closest-path upper-closest-path rotation index) chord-span - Either a single integer or a list of integers specifying the maximum span (in semitones) for chord splitting:mSingle integer: Applies the same span to all chord-splitting events. List of integers: The function loops over the list cyclically if there are more splitting events than list elements. sequence - An OMN sequence or list of sequences where each chord or event may include duration, pitch, velocity, and articulation. lower-size - (optional; default: NIL) Specifies the chord size for the lower register: Single integer: Applies the same size to all chords. List of integers: Cycles through the list for successive chords. upper-size - (optional; default: NIL) Specifies the chord size for the upper register: Single integer: Applies the same size to all chords. List of integers: Cycles through the list for successive chords. lower-ambitus - (optional; default: NIL) A list of two integers (low high) specifying the ambitus range for the lower register. The ambitus function is applied to the result. upper-ambitus - (optional; default: NIL) A list of two integers (low high) specifying the ambitus range for the upper register. The ambitus function is applied to the result. lower-transposition - (optional; default: NIL) An integer specifying the transposition interval for the lower register. upper-transposition - (optional; default: NIL) An integer specifying the transposition value of the result of the upper register. lower-closest-path - (optional; default: NIL) Boolean (T or NIL). If T, the closest-path function is applied to the lower register. upper-closest-path - (optional; default: NIL) Boolean (T or NIL). If T, the closest-path function is applied to the upper register. rotation - (optional; default: NIL) A single integer or a list of integers specifying the rotation (harmonic inversion) of the chord. Single integer: Applies the same rotation to all chords. List of integers: Cycles through the list for successive chords. index - (optional; default: NIL) An optional variable name to which the final two-part structure is assigned. If NIL, the function return a list of two sublists. Description: SPLIT-CHORD reconstructs a chordal OMN sequence into a two-part score, typically representing the left-hand and right-hand parts of a piano performance. The function operates based on chord-span constraints (defining the maximum allowable range in semitones for each individual part after splitting) and chord size constraints (defining the number of pitches assigned to the lower and upper parts). By carefully controlling these parameters, the function enables precise division of complex chordal sequences into manageable and musically meaningful components. The splitting process adheres to the following rules: Multi-note chords: Depending on the specified chord-span and size constraints, multi-note chords are either split into two parts (upper and lower) or assigned entirely to one part, with a rest inserted in the other. Single pitches: Individual pitches are allocated based on their range. By default, pitches below 0 (e.g., (0 = c4) -39 to -1) are assigned to the lower part, and pitches between 0 and 48 are assigned to the upper part. Rests or negative durations: Events with no pitches or a negative duration are duplicated in both parts, placing identical rests in each. When chord-span, lower chord size, and upper chord size are provided as lists of integers, the function applies these constraints sequentially to successive chord-splitting events. If the number of chords exceeds the length of one or more lists, the function loops through the lists cyclically. This cyclical behaviour allows for dynamic and evolving splits, creating variation in the resulting two-part score. For example, if chord-span = '(13 6 4) and the sequence contains five chords to split, the spans used will be 13, 6, 4, 13, and 6, repeating as necessary. Similarly, if :lower-size is (2 0 3) and :upper-size is (1 3 0), the chord sizes for each part will follow these patterns cyclically for successive chords. The function supports additional flexibility through parameters like rotation, which applies harmonic inversion to chords, and ambitus, which constrains pitches to specified ranges for the lower and upper parts. Transposition and closest-path adjustments can further refine the results, ensuring the output adheres to specific musical or performance requirements. SPLIT-CHORD is a versatile tool for converting chordal sequences into structured two-part scores, suitable for piano or other polyphonic instruments, while maintaining control over pitch distribution and musical coherence. Example 1 Basic chord splitting: (setf seq1 '((-e. e. c1cs2bb2b3 p q. e1bb2b3cs4 mp e. bb2b3cs4e4bb4 s bb2eb3g3b3d4 tie) (e bb2eb3g3b3d4 mp h. b2b3d4g4bb4 p e c1cs2bb2b3d4 mp))) In this example, the chord-span is set to 13 semitones, defining the maximum allowable pitch range for each individual part after splitting. No additional constraints are applied to the chord sizes for the upper or lower parts, resulting in a straightforward division into two balanced parts. (split-chord 13 seq1) Varying chord spans per chord: (split-chord '(6 13 6 13 4 4) seq1) In this example, the chord-span remains at 13 semitones. Chord size constraints are applied such that the upper part is limited to two pitches per chord (:upper-size 2), while the lower part follows a sequence of chord sizes specified as (2 2 0 3 0) (:lower-size). Here, 0 indicates that the chord is replaced by a rest in the lower part. The function cycles through the list for successive chords, creating a texture where the upper part consistently carries harmonic content, while the lower part alternates between chords (two or three pitches) and rests. (split-chord 13 seq1 :upper-size 2 :lower-size '(2 2 0 3 0)) In the next example, the chord-span remains at 13 semitones, but both parts alternate between rests and harmonic content. The lower part follows a sequence of sizes (2 0 2 0 2) (:lower-size), where 2 specifies two pitches and 0 indicates a rest. The upper part follows a complementary sequence of (0 2 0 2 0) (:upper-size), where rests alternate with two-note chords. This configuration creates an interlocking rhythmic texture, where one part is active while the other is silent. (split-chord 13 seq1 :lower-size '(2 0 2 0 2) :upper-size '(0 2 0 2 0)) Example 2 Chord progression (John Coltrane, Giant Steps): (setf giant-steps '((h (b3 maj7) (d3 7)) (h (g3 maj7) (bb3 7)) (w (eb3 maj7)) (h (a3 m7) (d3 7)) (h (g3 maj7) (bb3 7)) (h (eb3 maj7) (gb3 7)) (w (b3 maj7)) (h (f3 m7) (bb3 7)) (w (eb3 maj7)) (h (a3 m7) (d3 7)) (w (g3 maj7)) (h (cs3 m7) (fs3 7)) (w (b3 maj7)) (h (f3 m7) (bb3 7)) (w (eb3 maj7)) (h (cs3 m7) (fs3 7)))) In this example, the chord-span is set to 13 semitones, which defines the maximum pitch range for each individual part after splitting. Larger chords are divided so that the pitches assigned to the lower part stay within a 13-semitone range, and similarly for the upper part. No additional parameters are specified, so the chords are split purely based on this chord-span constraint. (split-chord 13 giant-steps) Adding rotation and closest-path adjustment: In this example, the chord-span remains at 13 semitones, but additional parameters are applied to introduce more complexity and variation: Rotation (:rotation '(-2 -1 0 1 2 3 2 1 0 -1)): This applies a sequence of harmonic inversions to the chords, shifting their pitches cyclically for successive events. The rotation pattern follows the specified list, repeating as necessary, and introduces harmonic variation to the progression. Upper closest-path (:upper-closest-path t) Ensures that the notes assigned to the upper part follow the closest pitch progression, minimising leaps between successive chords. This results in smoother melodic movement in the upper part. (split-chord 13 giant-steps :rotation '(-2 -1 0 1 2 3 2 1 0 -1) :upper-closest-path t) Example 3 Alternating chord sizes: (setf seq2 '((5q g5eb5g4 mp f5b5eb6 mf d6cs6a5 mp g5eb5b4g4 p b5eb6g6bb6 mp) (5q eb6b5 p eb6 pp b5 gs5 g6 mp) (5q eb6g6 g5eb5b4g4 p eb6 f b5eb6g6 p f5b5eb6) (5q g5b5eb6g6 b5g5eb5 mp g6 p eb6g6 b5g6bb6))) (split-chord 13 seq2 :upper-size 1 :lower-size 2) A maximum range of 13 semitones is allowed for splitting each chord. The upper part is limited to a single pitch per chord (:upper-size 1). The lower part is assigned two pitches per chord (:lower-size 2). In the next example the chord-span remains at 13 semitones. Chord size constraints in both the upper part and the lower part are restricted to a single pitch per chord (:upper-size 1, :lower-size 1). The rotation (:rotation -1) applies harmonic inversion to each chord, effectively shifting the chord pitches downwards by one position cyclically. (split-chord 13 seq2 :upper-size 1 :lower-size 1 :rotation -1) Example 4 (setf seq3 '((s d3f3gs3c4e4g4 mf gs4 d4 d5) (s gs4 d3f3gs3c4e4g4 gs3 f5) (s d4 d3c4e4f4gs4d5 g4 gs4) (s d3c4e4f4gs4d5 d4 f3 gs5))) (split-chord 13 seq3 :upper-size 1 :lower-size 1 :rotation 1) This configuration results in a clear contrapuntal texture with each part featuring a single-note melodic line. The melodic and harmonic content is balanced between the two parts, while the rotation adds variety by altering the internal structure of the chords. (split-chord 13 seq3 :upper-size 2 :lower-size 1 :rotation 1 :upper-closest-path t) Closest-path adjustment (:upper-closest-path t ) Ensures that the notes assigned to the upper part follow the closest pitch progression, minimising large leaps in the melodic line. (split-chord 13 seq3 :upper-size 1 :lower-size 3 :rotation '(-1 0 1) :upper-ambitus '(0 24) :lower-ambitus '(-24 -6) :upper-transposition -12) In this example, the chord-span is set to 13 semitones, defining the maximum pitch range for each individual part after splitting. The upper part is restricted to a single pitch per chord (:upper-size 1), while the lower part is assigned three pitches per chord (:lower-size 3). The rotation parameter (:rotation '(-1 0 1)) applies a cyclic harmonic inversion, with each successive chord rotated by -1, 0, or 1 positions, respectively. The ambitus constraints further refine the pitch ranges: the upper part is limited to pitches between 12 and 24 (:upper-ambitus '(12 24)), and the lower part is constrained to pitches between -24 and -6 (:lower-ambitus '(-24 -6)). Additionally, the upper part is transposed down by an octave (:upper-transposition -12), ensuring that its pitches remain within a specific register. This configuration results in a two-part split where the lower part features rich, dense harmonies within the specified ambitus, while the upper part provides a sparse, single-note melodic line transposed into a lower register. The combination of rotation, ambitus constraints, and transposition creates a dynamic, texturally varied output with precise control over pitch distribution. Example 5 In the next example, we process and transform spectral partials into a chordal sequence and then apply the SPLIT-CHORD function to divide it into two parts. (setf partials (library 'marangona-frames 'partials nil :collect :all)) (setf frames (spectral-to-omn partials :resolution '5q :min-frame-size 2 :min-amp 0.01 :min-freq 10.0 :max-freq 2000.0)) (self events (rnd-sample 40 (single-events frames))) (self var-par (rnd-sample (length events) '(ro i))) (self var (pitch-variant events :variant var-par)) (self mel-sec (rndn 6 0 (length var))) (self mel (pitch-melodize var :section mel-sec)) (setf mat (omn-to-time-signature mel '(1 4))) (setf trans-par (rndn (length mat) -11 11)) (setf transp (pitch-transpose trans-par mat)) (self section (get-bar '(1..8) (quantize transp '(1 2 5)))) => ((5q g2g1e1gs1g1f1fs1g1a0bb0b0c1d1eb1g1gs1b1 cs1fs2f3g3bb3cs4fs4g4b4cs5eb5g5gs5b5eb6 . . .) (split-chord 13 section :upper-size 3 :lower-size 3) Best wishes, Janusz JulioHerrlein, Cliff and jesele 1 2 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.