Jump to content
Sign in to follow this  
torstenanders

Updated library of many custom Opusmodus functions

Recommended Posts

Dear all,


I updated my library tot (https://github.com/tanders/tot) in various ways. In particular, there are many new functions available.


You can now read the documentation online at https://tanders.github.io/tot/. However, remember that you can directly evaluate the many examples in the documentation when (after installing the library) you drag the library folder into your Opusmodus project navigator and open the documentation within Opusmodus.

 

If you are interested in the details of how the library developed, you can see a changelog at https://github.com/tanders/tot/commits/master .


NOTE: When you install/upgrade this library, make sure you also install/upgrade all its dependencies, as described in the detailed installation instructions at https://github.com/tanders/tot

 

Best,
Torsten
 

PS: This is not an official release. As I am primarily developing this library for my own purposes, I keep it rather informal and extend it on a continuous basis for my own composition projects. Anyway, I thought at least some of you might be interested to learn that there have been many developments 🙂

Share this post


Link to post
Share on other sites

Thanks, Torsten !

Very nice. I want to try it.

I did the Git terminal stuff

 

I don't  know how to to this part...

ASFD is something I have to install ?

 

???

Best,

Julio

 

USAGE part (???)

 

This library is an ASDF system (ASDF is the de facto standard for building Common Lisp software), and you can load it into your Lisp compiler as follows. All dependency libraries are loaded automatically as well.

(require :tot)

For most convenient use within Opusmodus, you can drag and drop the whole folder of this library in the browser of an Opusmodus project. Then, visit the HTML documentation of this library from within Opusmodus: open the tot, and then its doc folder and click on an HTML file, say index.html. You can now browse the reference documentation of the library, which explains its individual definitions. Most importantly, you can directly run all example code in the documentation from within Opusmodus (thanks, Janusz Podrazik).

added 1 minute later

Second question :

When I update to next Opusmodus release, do I have to reinstall it ?

Best,

Julio

Share this post


Link to post
Share on other sites

Dear Julio,

 

As the link you copied said, "ASDF is the de facto standard build facility for Common Lisp." In other words, it is the standard software for organising, compiling, loading etc. Common Lisp programs that consist of more than just one file. I think it is already built into CCL, the compiler used by Opusmodus. Have you tried after the installation to simply run the given Common Lisp command to load the library?

(require :tot)

>  When I update to next Opusmodus release, do I have to reinstall it ?

 

Not if you follow the installation instructions and install it in ~/common-lisp/

 

Best,

Torsten

 

Share this post


Link to post
Share on other sites

Dear Torsten,

Thank you. Now I understand that this command is done inside Opusmodus.

Unfortunately, I got some errors...

 

;Compiling "/Users/acme/common-lisp/string-tools/make-package.lisp"...
;Compiling "/Users/acme/common-lisp/string-tools/string-tools.lisp"...
;Compiling "/Users/acme/common-lisp/string-tools/export.lisp"...
;Compiling "/Users/acme/common-lisp/ta-utilities/make-package.lisp"...
;Compiling "/Users/acme/common-lisp/ta-utilities/my-utilities.lisp"...
;Compiling "/Users/acme/common-lisp/ta-utilities/export.lisp"...
;Compiling "/Users/acme/common-lisp/fenv/sources/make-package.lisp"...
;Compiling "/Users/acme/common-lisp/fenv/sources/macros.lisp"...
;Compiling "/Users/acme/common-lisp/fenv/sources/fenv.lisp"...
;Compiling "/Users/acme/common-lisp/fenv/sources/export.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/package.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/from-studio-flat.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/01.domain.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/02.engine.lisp"...
;Compiler warnings for "home:common-lisp;cluster-engine;sources;02.engine.lisp.newest" :
;   In poly-engine: type declaration for unknown variable master-index
;   In poly-engine: Undeclared free variable *debug-count-backtrack*
;   In an anonymous lambda form at position 22432: Duplicate definitions of assign-pitches-for-motif, in this file
;   In an anonymous lambda form at position 23073: Duplicate definitions of assign-pitches-for-nth-motif, in this file
;   In fail: Undeclared free variable *debug-count-backtrack* (2 references)
;   In an anonymous lambda form at position 36784: Duplicate definitions of backjump-engine, in this file
; Warning: Lisp compilation failed while compiling #<cl-source-file "cluster-engine" "sources/02.engine">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "cluster-engine" "sources/02.engine">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/03.Fwd-rules.lisp"...
;   In fwd-rule-indep: type declaration for unknown variable length-metric-engin
;   In fwd-rule2: type declaration for unknown variable length-metric-engin
;   In fwd-rule3: type declaration for unknown variable length-metric-engin
;   In fwd-rule4: type declaration for unknown variable length-metric-engin
;   In fwd-rule5: type declaration for unknown variable length-metric-engin
;   In fwd-rule6: type declaration for unknown variable length-metric-engin
;   In fwd-rule6b: type declaration for unknown variable length-metric-engin
; Warning: Lisp compilation failed while compiling #<cl-source-file "cluster-engine" "sources/03.Fwd-rules">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "cluster-engine" "sources/03.Fwd-rules">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/04.Backtrack-rules.lisp"...
;   In backtrack-rule2: type declaration for unknown variable highest-index
; Warning: Lisp compilation failed while compiling #<cl-source-file "cluster-engine" "sources/04.Backtrack-rules">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "cluster-engine" "sources/04.Backtrack-rules">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05.rules-interface.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05a.rules-interface-1engine.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05b.rules-interface-2engines.lisp"...
;Compiler warnings for "home:common-lisp;cluster-engine;sources;05b.rules-interface-2engines.lisp.newest" :
;   In get-start-nth-pointer-durations: type declaration for unknown variable rhythmseq
;   In get-end-nth-pointer-durations: type declaration for unknown variable rhythmseq
; Warning: Lisp compilation failed while compiling #<cl-source-file "cluster-engine" "sources/05b.rules-interface-2engines">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "cluster-engine" "sources/05b.rules-interface-2engines">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05c.rules-interface-2engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05d.rules-interface-2engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05e.rules-interface-2engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05f.rules-interface-3engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05g.rules-interface-any-n-engines.lisp"...
;Compiler warnings for "home:common-lisp;cluster-engine;sources;05g.rules-interface-any-n-engines.lisp.newest" :
;   In get-pitches-for-slices-of-notecounts: type declaration for unknown variable notecount
;   In get-pitches-for-slices-of-notecounts: type declaration for unknown variable voicenr
;   In get-pitches-for-slices-of-notecounts: type declaration for unknown variable notecount-slice
;   In replace-notecount-by-timepoint: type declaration for unknown variable timepoint
;   In replace-notecount-by-timepoint: type declaration for unknown variable notecountgroups
;   In get-durations-for-slices-of-notecounts: type declaration for unknown variable notecount
;   In get-durations-for-slices-of-notecounts: type declaration for unknown variable voicenr
;   In get-durations-for-slices-of-notecounts: type declaration for unknown variable notecount-slice
;   In get-timepoints-for-slices-of-notecounts: type declaration for unknown variable notecount
;   In get-timepoints-for-slices-of-notecounts: type declaration for unknown variable voicenr
;   In get-timepoints-for-slices-of-notecounts: type declaration for unknown variable notecount-slice
; Warning: Lisp compilation failed while compiling #<cl-source-file "cluster-engine" "sources/05g.rules-interface-any-n-engines">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "cluster-engine" "sources/05g.rules-interface-any-n-engines">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05h.rules-higher-level.lisp"...
;Compiler warnings for "home:common-lisp;cluster-engine;sources;05h.rules-higher-level.lisp.newest" :
;   In an anonymous lambda form at position 453: Duplicate definitions of melodic-statement-for-dur, in this file
; Warning: Lisp compilation failed while compiling #<cl-source-file "cluster-engine" "sources/05h.rules-higher-level">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "cluster-engine" "sources/05h.rules-higher-level">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05i.rules-stop-search.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/05n.rules-interface-nn-engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06.heuristic-rules-interface.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06a.heuristic-rules-interface-1engine.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06b.heuristic-rules-interface-2engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06c.heuristic-rules-interface-2engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06d.heuristic-rules-interface-2engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06e.heuristic-rules-interface-2engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06f.heuristic-rules-interface-3engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/06g.heuristic-rules-interface-any-n-engines.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/07.backjumping.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/08.decode.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/09.utilities.lisp"...
;Compiler warnings for "home:common-lisp;cluster-engine;sources;09.utilities.lisp.newest" :
;   In get-nr-for-engine-with-highest-index: type declaration for unknown variable engine
;   In remove-list-before-startpoint: type declaration for unknown variable endpoint
;   In get-durations-at-notecounts: type declaration for unknown variable notecount
;   In get-durations-at-notecounts: type declaration for unknown variable voicenr
;   In get-durations-at-notecounts: type declaration for unknown variable notecounts
;   In get-timepoints-at-notecounts: type declaration for unknown variable notecount
;   In get-timepoints-at-notecounts: type declaration for unknown variable voicenr
;   In get-timepoints-at-notecounts: type declaration for unknown variable notecounts
;   In get-timepoints-at-notecounts-one-voice: type declaration for unknown variable notecount
;   In get-timepoints-at-notecounts-one-voice: type declaration for unknown variable notecounts-all-voice
;   In get-timepoints-at-notecounts-one-voice: type declaration for unknown variable list-voicenrs
;   In remove-rests-and-gracenotes-from-durationlist: type declaration for unknown variable timepoints
;   In get-timepoints-from-any-timepoint-minus-nsteps-ignor-rests-and-gracenotes: type declaration for unknown variable vsolution
;   In get-events-from-any-timepoint-minus-nsteps-ignor-rests-and-gracenotes: type declaration for unknown variable vsolution
;   In get-notecounts-from-any-timepoint-minus-nsteps-ignor-rests-and-gracenotes: type declaration for unknown variable vsolution
;   In get-timepoints-from-any-timepoint-minus-nsteps-ignor-rests: type declaration for unknown variable vsolution
;   In get-events-from-any-timepoint-minus-nsteps-ignor-rests: type declaration for unknown variable vsolution
;   In get-notecounts-from-any-timepoint-minus-nsteps-ignor-rests: type declaration for unknown variable vsolution
;   In get-timepoints-from-any-timepoint-minus-nsteps-ignor-rests-simplify-gracenotes: type declaration for unknown variable vsolution
;   In get-timepoints-from-any-timepoint-minus-nsteps: type declaration for unknown variable vsolution
;   In get-notecounts-from-any-timepoint-minus-nsteps: type declaration for unknown variable all-events
;   In get-timepoints-from-any-timepoint-minus-nsteps-ignor-gracenotes: type declaration for unknown variable vsolution
;   In get-events-from-any-timepoint-minus-nsteps-ignor-gracenotes: type declaration for unknown variable vsolution
;   In get-timepoints-from-before-any-timepoint-minus-nsteps-ignor-gracenotes: type declaration for unknown variable all-onsets-no-gracenote-no-rest
;   In an anonymous lambda form at position 106661: Duplicate definitions of remove-rests-and-return-notecountlist, in this file
;   In matrix-trans: type declaration for unknown variable row
; Warning: Lisp compilation failed while compiling #<cl-source-file "cluster-engine" "sources/09.utilities">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "cluster-engine" "sources/09.utilities">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/09b.markov-tools.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/09c.cluster-energy-profile.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/12.debug-tools.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/13.convert-pmc-rules.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/_000.main-interface.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-engine/sources/export.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-rules/sources/package.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-rules/sources/utils.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-rules/sources/rhythm-rules.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-rules/sources/melody-rules.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-rules/sources/harmony-rules.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-rules/sources/counterpoint-rules.lisp"...
;Compiling "/Users/acme/common-lisp/cluster-rules/sources/export.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/slippery-chicken.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/utils.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/OMN-utils.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/score.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/rhythm.lisp"...
;Compiler warnings for "home:common-lisp;tot;sources;rhythm.lisp.newest" :
;   In an anonymous lambda form at position 65555: Duplicate definitions of total-duration, in this file and in "home:common-lisp;tot;sources;OMN-utils.lisp.newest"
; Warning: Lisp compilation failed while compiling #<cl-source-file "tot" "sources/rhythm">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "tot" "sources/rhythm">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/tot/sources/pitch.lisp"...
;Compiler warnings for "home:common-lisp;tot;sources;pitch.lisp.newest" :
;   In stretch-pitches: Undeclared free variable chord
; Warning: Lisp compilation failed while compiling #<cl-source-file "tot" "sources/pitch">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
; Warning: Lisp compilation had style-warnings while compiling #<cl-source-file "tot" "sources/pitch">
; While executing: uiop/lisp-build:check-lisp-compile-warnings, in process Listener-1(7).
;Compiling "/Users/acme/common-lisp/tot/sources/velocity.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/articulations.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/PWGL.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/constraints.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/form.lisp"...
;Compiling "/Users/acme/common-lisp/tot/sources/orchestration.lisp"...
:tot
nil
89 > 
:tot
nil
89 > 

 

Share this post


Link to post
Share on other sites

Actually, these are warnings and not errors. They point out various issues in the code that could be improved (in particular in the library cluster engine, as you may have noticed), but the code should still work overall. Also, you should see these compilation and warning messages only once (if you never change the code of the relevant library).

 

Just try to go on and actually run some examples of these libraries. 

 

Please let me know if you run into an actual error message. (There are some minor bugs of course, but at least for my tot library I try to make them explicit in the documentation as well.)

 

Best,

Torsten

Share this post


Link to post
Share on other sites

> I like the Carnatic Stuff.

 

To best understand what those functions offer I recommend the book referenced in the doc (Reina, 2016), which was quite an eye-opener for me. There is a partial preview at Google Books (https://books.google.co.uk/books?id=4RSrCwAAQBAJ&amp;printsec=frontcover#v=onepage&amp;q&amp;f=false), and further information is available at the associated websites (http://www.contemporary-music-through-non-western-techniques.com and http://www.rafaelreina.org/book-online-material.html).

 

Best,

Torsten

 

References

Reina, R. (2016) Applying Karnatic Rhythmical Techniques to Western Music. Routledge.
added 8 minutes later

I just noticed the perhaps most important Karnatic function so far, gen-karnatic-cell, is not contained in the automatically generated documentation, because the documentation tool seemingly skips functions that are not defined at the top level. I may fix that at some stage, but for now you can read the documentation in the doc string of the function in its source file (rhythm.lisp), or you evaluate the following line and read it in the listener.

 

(documentation 'gen-karnatic-cell 'function)

 

Best,

Torsten

 

Share this post


Link to post
Share on other sites

I got just four 16th notes.

 

This function allows for various controls that you did not use – Of course this function also allows for plain sequences of 1/16-notes, when you select its arguments accordingly 🙂   I am interested in CAC as a means of control on a higher level instead of some automatic "magic".

 

You might want to run the examples below in Opusmodus to get music notation outputs, which are likely more easy to read than the OMN expressions, but nevertheless I provide the OMN expressions for completeness as well.

 

The argument position (3rd argument) controls the kind of rhythmic cell that you get, see the doc for details. Here is an example where different rhythmic cells are returned. Note that by default all returned cells carry potentially a durational accent. 

 

(gen-karnatic-cell 4 4 '(0 4 3 2 1 0))
=> ((1/4) (1/16 1/16 1/16 1/16) (1/8 1/16 1/16) (1/8 1/8) (3/16 1/16) (1/4))

 

Now, if you use the same positions but different gati or jathi settings then you get a somewhat similar rhythm in that different gati/jathi. Below I slightly adapted the positions to make the results even more similar. 

 

(gen-karnatic-cell 4 5 '(0 6 3 2 1 0))
=> ((5/16) (1/16 1/16 1/16 1/16 1/16) (3/16 1/16 1/16) (3/16 1/8) (1/4 1/16) (5/16))

 

You can, of course, use these in a different time signature (e.g., the tala of your choice).

 

(omn-to-time-signature (gen-karnatic-cell 4 5 '(0 6 3 2 1 0)) '(4 4))
=> ((q c4 tie s s s s s s e. s s s tie) (e c4 c4 q s q tie s))

 

If you want to keep track of where the accents are located, you could mark them before this transformation (the function articulate-phrase is defined below this post). You could then manually later revise the notation to instead you the beam-breaking that Reina recommends. 

 

(omn-to-time-signature 
 (articulate-phrase (gen-karnatic-cell 4 5 '(0 6 3 2 1 0))
                    :accent 'marc)
'(4 4))

=> ((q c4 tie+marc s marc s marc s s s s e. marc s s s tie+marc) (e c4 c4 q marc s q tie+marc s marc))
 

After the changed jathi above, here is a different gati. Results are more similar, because the underlying data is the same with different gati but the same jathi. Here is an example with quintuplets. 

 

(gen-karnatic-cell 5 4 '(0 4 3 2 1 0))
=> ((1/5) (1/20 1/20 1/20 1/20) (1/10 1/20 1/20) (1/10 1/10) (3/20 1/20) (1/5))

 

Here is the same with triplets -- exactly the same, only slower. 

 

(gen-karnatic-cell 3 4 '(0 4 3 2 1 0))
=> ((1/3) (1/12 1/12 1/12 1/12) (1/6 1/12 1/12) (1/6 1/6) (1/4 1/12) (1/3))


You can also change the jathi (or even gati) on the fly in a phrase. The given pattern is then 'cycled through'.

 

(gen-karnatic-cell 4 '(5 5 3 3) '(0 6 3 2 1 0))

=> ((5/16) (1/16 1/16 1/16 1/16 1/16) (1/16 1/16 1/16) (1/16 1/16 1/16) (1/4 1/16) (5/16))


You can also randomise your position

 

(gen-karnatic-cell 4 5 '(0 1 ? ? 0))

=> ((5/16) (1/4 1/16) (3/16 1/8) (3/16 1/16 1/16) (5/16))


And I did not even start discussing the other parameters yet. For example, you can set whether or not cells start with a durational accent (not a karnatic concept, but very useful notion for Western ears when dealing with rhythm). 

 

(gen-karnatic-cell 4 5 '(3 3 3 3) :accented? '(T nil nil T))

=> ((3/16 1/16 1/16) (1/16 3/16 1/16) (1/16 3/16 1/16) (3/16 1/16 1/16))

 

You can filter in various ways want kind of rhythm you want, e.g., set the minimum or maximum number of notes per cell. 

 

(gen-karnatic-cell 4 5 '(? ? ? ?) :min-number '(3 3 3 3) :seed 1)

=>((1/8 1/8 1/16) (3/16 1/16 1/16) (1/16 1/16 1/16 1/16 1/16) (1/8 1/8 1/16)) 

 

EDIT: Oops, that are is seemingly not fully working as expected.

 

I stop here and refer you do the documentation for more details: there are several more arguments that I did not even mention yet. I know that my documentation is rather concise and not a textbook, but it briefly discusses every detail. I said from the beginning, I wrote this for myself, so you might want to first spend a bit of time with the doc 🙂

 

As you hopefully can see, this function alone allows for a rather rich world of rhythm with rather precise control that allows varying some rhythmic idea in various ways. I am interested here in clearly perceivable rhythmic similarities, e.g., between rhythms in different gati and jathi combinations in the Western tradition of thematic variation.  

 

Of course, you can also process the result further in various ways. E.g., I am adding ties after long notes and/or subdivide short notes to increase the rhythmic contrast, and I am turning certain notes into rests...
 

Best,

Torsten

 

(defun articulate-phrase (sequence &key (accent 'marc))
  "Add articulations to phrase for more clear rhythmic accents, e.g, an accent on every first beat
.
  
  NOTE: This function assumes that `sequence' is a purely rhythmic OMN expression with only length values and perhaps ties. However, a sequence with (constant) pitches is returned, because certain Opusmodus functions do not support an OMN sequence without pitches.

  Examples:
  (articulate-phrase '((h h) (q q q q tie) (q q q q) (-q q) (q q q q)) :accent 'marc)
  => ((h marc h) (q marc q q q tie) (q q q q) (-q q) (q marc q q q))
  "
  (cons 
   ;; First bar
   ;;; NOTE: code repetition...
   (let ((bar1 (first sequence)))
     (if (length-notep (first bar1))
       (if (and (= (count-notes bar1) 1)
                (eql (first (last bar1)) 'tie))
         (tu:replace-element (merge-articulations (list accent 'tie)) 1 bar1)
         (tu:insert-after bar1 0 accent))
       bar1))
   ;; other bars
   (loop :for (bar1 bar2) :on sequence :while bar2
     ;;; NOTE: code repetition
     :collect (if (and (length-notep (first bar2))
                       (not (eql (first (last bar1)) 'tie)))
                (if (and (= (count-notes bar2) 1)
                         (eql (first (last bar2)) 'tie))
                  (tu:replace-element (merge-articulations (list accent 'tie)) 1 bar2)
                  (tu:insert-after bar2 0 accent))
                bar2))))

 

Share this post


Link to post
Share on other sites

Wow! Just installed and ran some examples from your docs...thank you Torsten for sharing this, and all your hard work to document and help install.

 

I will simply echo "lviklund" and say, "This is brilliant!" ;-)

Share this post


Link to post
Share on other sites

all your hard work to document

 

I actually do such detailed documentation for my own benefit as well. I once spent several months on developing some personal library that I used for composing some piece, but when I wanted to re-use it some two years later, I could not really understand my own functions anymore. Since then I better err on the side of overdoing the docs 🙂

 

Best,

Torsten

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×