Jump to content

Parametric Tintinntabuli


Recommended Posts

Hello!

 

I’m trying to approach a (sort of) contrapuntal composition style many know from Arvo Part as Tintinntabuli. The method is generally a tonal-based approach. I didn't see anything in the forums about it so I'm hoping this post isn't a duplicate.

 

My understanding of it is as follows:

 

1. In a key, say B minor, we have a melody line that could be:

 

(Setf pitches ‘(cs3 d3 g3  e3 fs3 b3))

 

This would be the M-line (melody line)

 

Underneath we would have one or more T-lines (tintinntabuli). Each would consist only of the B minor triad. The pitch of the triad in the T-line corresponds to the pitch in the triad determined by the rule established by the composer. This can be inferior or superior. So I could have a T1 line that is comprised of the first inferior diatonic pitch the pitch in the M Line and a T2 line comprised of the second inferior diatonic pitch.

 

So the T1 line would only consist of B, D and F#. To do this manually would be:

 

;; M1 Line

(Setf pitches ‘(cs3 d3 g3  e3 fs3 b3))

 

;; T1 Line

(Setf pitches ‘(b3 b3 fs3  d3 d3 fs2))

 

What I’m trying to do is automate the creation of the T1 or T2 lines parametrically.

 

Any advice on the best approach to this?

 

Thanks!

 

Tom Tolleson

Link to comment
Share on other sites

I once implemented a version of this in PWGL with constraint programming (rule based programming) and the help of pwgl-cluster-engine and pwgl-cluster-rules. Unfortunately, I PWGL is meanwhile broken for me, and I cannot open this patch anymore, but just in case you have used PWGL and these libraries before, I attach a patch demonstrating it.

 

If not, then this likely will not really help you. Sorry that I cannot help more. Its about 10 years ago since I did this...

 

Best,

Torsten

 

04-tintinnabuli.pwgl

Link to comment
Share on other sites

Dear Tom,

 

Maybe it would be easier if you specify what kind of "rule" you imagine to implement the sequences.

After that you could imagine many different ways to put this in movement, like randomizing the notes of the lines, shuffling the lines in a more specific way.

And how would be the rhythmic and texture treatment ? And the instrumentation / voice layers ?

 

Best ! 

Link to comment
Share on other sites

"I once implemented a version of this in PWGL "

 

 

Thanks for finding this! I do not have any of these libraries nor use PWGL but I appreciate you jumping in!

 

14 minutes ago, JulioHerrlein said:

Dear Tom,

 

Maybe it would be easier if you specify what kind of "rule" you imagine to implement the sequences.

After that you could imagine many different ways to put this in movement, like randomizing the notes of the lines, shuffling the lines in a more specific way.

And how would be the rhythmic and texture treatment ? And the instrumentation / voice layers ?

 

Best ! 

Thanks, Julio!


I'm imagining a melody line of pitches and a "bag" array of the diatonic pitches for that key. Based on the pitch of the m line, the algorithm would select the closest inferior pitch from the diatonic array. Likely there would be a pitch-to-integer conversion to find the smallest difference between the melody line and the pitches in the "bag."

I am thinking of this in Machine Learning terms as a K-means "nearest neighbor" approach which likely won't help me in Lisp!

 

Tom

Link to comment
Share on other sites

My direction now is beginning with

(setf mline '(d3 e3 d3 a3 f3 g3 c3))
(setf mlinecount (get-count mline :length :note))

(setf tline (rnd-sample mlinecount '(c3 e3 g3)))


I just need to figure out how to replace the 

rnd-sample

function with a function that finds the next lowest pitch from (c3 e3 g3), and of course I could also just create a variable out of (c3 e3 and g3) but I hope you get my point.

Link to comment
Share on other sites

The find-closest could do the job but I'm having some difficulty implementing it with variables rather than integers

 

;; establish mline and tline (in this case just randomizing the tline)

(setf mline '(d3 e3 d3 a3 f3 g3 c3))
(setf tline (rnd-sample mlinecount '(c3 e3 g3)))

;; convert pitches to integer. Both of these work properly. I'm just trying to create variables with integers to apply into the "find-closest" function.
(setf mlineint (pitch-to-integer mline)) 
(setf tlineint (pitch-to-integer tline))

;; The following sample of "find-closest" works properly
(find-closest 5 '(6 2 8 3))

;; the following howevfer does not
(find-closest mlineint '(tlineint))

 

Link to comment
Share on other sites

Hi,

 

I've made some Tintinabuli test long time ago in Opusmodus but don't remember if it was correctly implemented or not....

Also all of this tests are broken because using a very old version of Opusmodus.

I don't have time to fix them all now but I quick fixed the first one I found with actual Opusmodus correct functions.

 

Don't know if that one is correct regarding the "rules" but may be it could help you a bit.

 

This subject interest me as well and if I find a bit of time, I will explore it deeper this year.

 

Best

 

SB.

 

;;;---------------------------------------------------------
;;; Parameters
;;;---------------------------------------------------------

(setf size 8)
(setf bars (gen-repeat size '(4/4)))
(setf pause (length-span bars '(-q)))

(setf ph1.size 8)
(setf bars (gen-repeat size '(4/4)))
(setf pause (length-span bars '(-q)))

(setf mode1 '(dorian :root d4))
(setf ph1.pitch (filter-repeat
                1
                (tonality-map
                 mode1
                (integer-to-pitch
                (vector-round 
                 0 16 
                 (vector-smooth
                  0.36
                  (gen-white-noise 256 :seed 772)))))))

(setf ph1.len (euclidean-rhythms 
              (gen-repeat ph1.size '(9))
              '(1)
              '(5)
              :seed 93
              :binary-to-length t
              :len-val 'e
              ))


;; Antécédent
(setf ph1.omn
      (make-omn
       :pitch ph1.pitch
       :length ph1.len
       ))

;; Conséquent
(setf ph1b.omn (ambitus
                '(0 16) (tonality-map mode1 (pitch-variant ph1.omn :variant 'i))))

(setf ph1 (assemble-seq ph1.omn ph1b.omn))

;; Tintinabuli
;; V1
(setf tint1a.pitchlist '(c4 e4 g4))
(setf tint1a.pitch (rnd-sample (* ph1.size 4) tint1a.pitchlist))
(setf tint1a.len (euclidean-rhythms 
                (gen-repeat (length ph1) '(9))
                '(1)
                '(2)
                :seed 103
                :binary-to-length t
                :len-val 'e
                ))

(setf tint1a.omn (filter-tie
                (tonality-map
                mode1
                (make-omn
                :pitch tint1a.pitch
                :length tint1a.len
                ))))

(setf tint1a tint1a.omn)

;; V2
(setf tint1b.pitchlist '(c3 e3 g3))
(setf tint1b.pitch (rnd-sample (* ph1.size 4) tint1b.pitchlist))
(setf tint1b.len (euclidean-rhythms 
                (gen-repeat (length ph1) '(9))
                '(1)
                '(2)
                :seed 19
                :binary-to-length t
                :len-val 'e
                ))

(setf tint1b.omn (filter-tie
                (tonality-map
                mode1
                (make-omn
                :pitch tint1b.pitch
                :length tint1b.len
                ))))

(setf tint1b tint1b.omn)

;; V3
(setf tint1c.pitchlist '(c2 e2 g2 c3))
(setf tint1c.pitch (rnd-sample (* ph1.size 4) tint1c.pitchlist))
(setf tint1c.len (euclidean-rhythms 
                (gen-repeat (length ph1) '(9))
                '(1)
                '(2)
                :seed 17662
                :binary-to-length t
                :len-val 'e
                ))

(setf tint1c.omn (filter-tie
                (tonality-map
                mode1
                (make-omn
                :pitch tint1c.pitch
                :length tint1c.len
                ))))

(setf tint1c tint1c.omn)







(setf soprano ph1)
(setf alto tint1a)
(setf tenor tint1b)
(setf bass tint1c)


;;;---------------------------------------------------------
;;; Score and Layout
;;;---------------------------------------------------------

(def-score choir-satb
           (:title "Title"
            :composer "Composer"
            :copyright "Copyright © "
            :key-signature 'chromatic
            :time-signature '((1 1 1 1) 4)
            :tempo 100
            :layout (choir-satb-layout
                     'soprano 'alto 'tenor 'bass))
  
  (soprano
   :omn soprano
   :channel 1
   :sound 'gm
   :program 'choir-aahs
   :volume 100
   :pan 16
   :controllers (91 '(48))
   )
  
  (alto
   :omn alto
   :channel 2
   :sound 'gm
   :program 'choir-aahs
   :volume 100
   :pan 41
   :controllers (91 '(48))
   )
  
  (tenor
   :omn tenor
   :channel 3
   :sound 'gm
   :program 'choir-aahs
   :volume 100
   :pan 86
   :controllers (91 '(48))
   )
  
  (bass
   :omn bass
   :channel 4
   :sound 'gm
   :program 'choir-aahs
   :volume 100
   :pan 111
   :controllers (91 '(48))
   )
  )

 

Link to comment
Share on other sites

On 1/4/2023 at 11:19 AM, torstenanders said:

I once implemented a version of this in PWGL with constraint programming (rule based programming) and the help of pwgl-cluster-engine and pwgl-cluster-rules. Unfortunately, I PWGL is meanwhile broken for me, and I cannot open this patch anymore, but just in case you have used PWGL and these libraries before, I attach a patch demonstrating it.

 

If not, then this likely will not really help you. Sorry that I cannot help more. Its about 10 years ago since I did this...

 

Best,

Torsten

 

04-tintinnabuli.pwgl 69.95 kB · 2 downloads

Dear Torsten, about Cluster Engine, have you got some plans to implement this wonderful tool into the new Opusmodus V3 ? as well as your great others libraries like Fenv and others ?

 

Best

 

Stéphane

Link to comment
Share on other sites

Dear Stéphane and Tom

 

I did some edits in the Stéphane´s code. Some functions had names changed.

 

Hope it can help.

Best,

Julio

 

;;;---------------------------------------------------------
;;; Parameters
;;;---------------------------------------------------------

(setf size 8)
(setf bars (gen-repeat size '(4/4)))
(setf pause (length-span bars '(-q)))

(setf ph1.size 8)
(setf bars (gen-repeat size '(4/4)))
(setf pause (length-span bars '(-q)))

(setf mode1 '(dorian :root d4))
(setf ph1.pitch (filter-repeat
                1
                (tonality-map
                 mode1
                (integer-to-pitch
                (vector-round 
                 0 16 
                 (vector-smooth
                  0.36
                  (gen-white-noise 256 :seed 772)))))))

(setf ph1.len (euclidean-rhythm 
              (gen-repeat ph1.size '(9))
              1
              5
              1/8
              :seed 93))
             ; :binary-to-length t)
             ; :len-val 'e
             ; ))


;; Antécédent
(setf ph1.omn
      (make-omn
       :pitch ph1.pitch
       :length ph1.len
       ))

;; Conséquent
(setf ph1b.omn (ambitus
                '(0 16) (tonality-map mode1 (pitch-variant ph1.omn :variant 'i))))

(setf ph1 (assemble-seq ph1.omn ph1b.omn))

;; Tintinabuli
;; V1
(setf tint1a.pitchlist '(c4 e4 g4))
(setf tint1a.pitch (rnd-sample (* ph1.size 4) tint1a.pitchlist))
(setf tint1a.len (euclidean-rhythm 
                (gen-repeat (length ph1) '(9))
                1
                2
                1/8
                :seed 103))
               ; :binary-to-length t
               ; :len-val 'e
               ; ))

(setf tint1a.omn (filter-tie
                (tonality-map
                mode1
                (make-omn
                :pitch tint1a.pitch
                :length tint1a.len
                ))))

(setf tint1a tint1a.omn)

;; V2
(setf tint1b.pitchlist '(c3 e3 g3))
(setf tint1b.pitch (rnd-sample (* ph1.size 4) tint1b.pitchlist))
(setf tint1b.len (euclidean-rhythm 
                (gen-repeat (length ph1) '(9))
                1
                2
                1/8
                :seed 19))
               ; 1/8))
               ; :binary-to-length t
               ; :len-val 'e
               ; ))

(setf tint1b.omn (filter-tie
                (tonality-map
                mode1
                (make-omn
                :pitch tint1b.pitch
                :length tint1b.len
                ))))

(setf tint1b tint1b.omn)

;; V3
(setf tint1c.pitchlist '(c2 e2 g2 c3))
(setf tint1c.pitch (rnd-sample (* ph1.size 4) tint1c.pitchlist))
(setf tint1c.len (euclidean-rhythm 
                (gen-repeat (length ph1) '(9))
                1
                2
                1/8
                :seed 17662))
               ; :binary-to-length t
               ; :len-val 'e
               ; ))

(setf tint1c.omn (filter-tie
                (tonality-map
                mode1
                (make-omn
                :pitch tint1c.pitch
                :length tint1c.len
                ))))

(setf tint1c tint1c.omn)


(setf v1 ph1)
(setf v2 tint1a)
(setf v3 tint1b)
(setf v4 tint1c)


;;;---------------------------------------------------------
;;; Score and Layout
;;;---------------------------------------------------------


(ps 'gm
     :sq 
(list 
(pitch-transpose 0 (ambitus 'violin v1)) 
(pitch-transpose 0 (ambitus 'violin v2)) 
(pitch-transpose 0 (ambitus 'viola v3)) 
(pitch-transpose 0 (ambitus 'cello v4))
)
    :key-signature 'atonal 
    :tempo 90
    :flexible-clef nil 
    :rewrite-lengths nil 
    :accidentals :cautionary
    :merge-rests nil 
)

 

Link to comment
Share on other sites

  • 3 weeks later...
On 1/5/2023 at 1:07 PM, JulioHerrlein said:

Dear Stéphane and Tom

 

I did some edits in the Stéphane´s code. Some functions had names changed.

 

Hope it can help.

Best,

Julio

 

 

This works perfectly Julio. This provides some solid building blocks. Thanks Julio and Stephane!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

Terms of Use Privacy Policy