Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by torstenanders

  1. 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 🙂
  2. torstenanders

    Updated library of many custom Opusmodus functions

    > 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
  3. For sound synthesis purposes (e.g., for an expressive performance), we may want to use note lengths beyond the restricted set of quantised note durations. However, Opusmodus currently prevents various irregular note duration sequences to be auditioned and throws an error instead. What is really interesting, though, is that the notation for such irregular durations still seem to work. It might make sense the other way round (i.e. refusing to notate certain rhythms -- though I am definitely not voting for introducing that :), but I don't see any real reason why arbitrary rhythms may not be auditioned. As an example, below is a short example of some arbitrary non-regular rhythm. Opusmodus can notate this rhythm, but when trying to play it back it throws an error. '((1/10 1/11 1/12 1/13)) Thanks! Best, Torsten
  4. torstenanders

    Updated library of many custom Opusmodus functions

    > 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))))
  5. torstenanders

    Updated library of many custom Opusmodus functions

    > 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&printsec=frontcover#v=onepage&q&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
  6. torstenanders

    Updated library of many custom Opusmodus functions

    Good to hear things are working for you 😉 Note that dependencies of this library are of interest on their own for computer-aided composition. This is particularly true for the constraint library cluster engine and its extension cluster rules, as well as the library fenv. Torsten
  7. torstenanders

    Updated library of many custom Opusmodus functions

    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
  8. torstenanders

    Updated library of many custom Opusmodus functions

    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
  9. It is handy that Opusmodus can display multiple score snippets and full scores alongside each other. Is there perhaps also a way to re-play some snippet still shown? Either with some GUI element that I may have missed or programmatically (they all have a unique name shown, like "UNTITLED 101 (Snippet)").? There is a function audition-musicxml-last-score, is there perhaps a function to again audition a score that is specified by its name? Thanks! Best, Torsten
  10. torstenanders

    How to force a time signature for Snippet fast use

    Great. How do we document such features so that there is an obvious place for them for new users? Best, Torsten
  11. Dear all, I am working on porting libraries from other algorithmic composition environments so that they are usable in Opusmodus. The library Cluster Engine is a constraint solver for solving polyphonic constraint satisfaction problems where both the pitch and the rhythmic structure can be restricted by an arbitrary number of constraints (rules), and a constraint solver then searches for a solution that is consistent with all constraints. This library supports user-defined rules, and highly flexible ways to control which aspects of the resulting score are controlled by certain rules. For example, you can independently control with compositional rules the melody and harmony of the music you generate. The library Cluster Rules is extension of Cluster Engine that provides predefined rules and some utilities. Plain Common Lisp versions of these libraries are available at https://github.com/tanders/cluster-engine and https://github.com/tanders/cluster-rules, together with installation instructions etc. These libraries are very powerful, e.g., I use them to revise the underlying harmony of preexisting Opusmodus scores such that the result follows standard voice leading rules etc. However, these libraries may be somewhat tricky to learn, in particular if you never before had any contact with constraint programming. I therefore recommend to start learning these libraries first in PWGL, where their documentation is better (they come with interactive tutorials). Best, Torsten
  12. torstenanders

    Ported PWGL libraries: Cluster Engine and Cluster Rules

    Dear Achim, From your error message at the end (There is no package named "PW" ) it looks like you did not follow the installation instructions, which you can find at https://github.com/tanders/cluster-engine In a nutshell, you should load it with ASDF and for that put it at a location where ASDF can find it. Instead, when you are putting it into ~/Opusmodus/Extensions/ then files are loaded in a wrong order. Best, Torsten
  13. torstenanders

    Orchestral Template EastWest HW Orch and Plogue Bidule

    I just got a copy of EW ComposerCloud and had a look at this. Wow -- this setup is a true monster, and way too much for my poor mere 8GB laptop (with unfortunately no way to extend the memory). I can confirm that in principle your setup works on my computer (Opusmodus can control sound playback of the instruments), but even when I reduce the bidule-file to only the string section, my machine has difficulties handling it. Sigh. How much memory are you using? I wish Play would have a purge feature similar to Kontakt, where you can basically start with an empty patch, and all samples needed are by and by loaded. (Play has some purge functionality, but it is more limited, only useful when the score is already fixed, which is not terribly useful in an environment like Opumodus). (I would probably need a second computer and something like Vienna Ensemble Pro to handle a full orchestra, in particular as I would be interested in using multiple articulations...) In your setup, you are running a separate Play instance for each instrument, and then you load several articulations per instrument into that Play instance, each on a different MIDI channel. I don't quite understand how this should work, as each instrument is controlled by only a single MIDI channel. Best, Torsten
  14. I like how the function tonality-map allows specifying some input harmony (called tonality) and raw music, where the "raw" music is then quasi-quantised into the given harmony. However, I would like to control in which octaves specific tones are allowed to occur. tonality-map allows specifying an underlying harmony that ranges over multiple octaves, but it seems that internally only octave-less pitch classes are used, and any tone in the harmony can occur in any octave in the result. By contrast, in the spectral tradition of music thinking, you change the underlying spectrum if you scramble in which octaves pitches occur. For example, if you have a spectrum or chord that approximates the overtone series, then that spectrum sounds rather consonant, regardless how far up in the overtone series you allow tones to be included. However, if you then randomly octave-transpose the pitches of this spectrum/chord, then it can become much more dissonant, without changing any pitch classes. To be more specific here is a dummy example with simple traditional chords where tones are distributed across octaves in a certain way. (tonality-map ;; underlying harmony or spectra '((c4g4e5b5d6) (g3d4b5f5a4)) ;; input music '((h c4f5 cs4fs5) (d4g5 cs4gs5) (eb4as5 f4a5) (e4gs5 c4gs5)) ;; harmonic rhythm :time '(w w w_w)) => ((h c4e5 c4g5) (h a3d5 g3d5) (h e4b5 e4b5) (h e4g5 c4g5)) As you can see, the tone G in the first tonality occurs only in octave 4, but in the result, in the second chord of the first bar (still following the first tonality) we have a g5 instead. Now, you might feel that the g5 does not musically do any harm, but in the second tonality, there is an A only in octave 6, while in the function output in the related third chord the A occurs three octaves lower in octave 3, where it greatly increases the dissonance degree of this chord/scale. So, is there a way to restrict the octaves of tones in the result to be restricted to the octaves of these tones in the respective tonalities? Alternatively, is there another function that complements tonality-map, where I can force some "raw" music to follow some underlying harmony with a given harmonic rhythm, and where the octaves of the resulting pitches can be restricted? Thank you! Best, Torsten
  15. torstenanders

    tonality-map: controlling in which octave tones occur

    I assume internally of tonality-map there is a comparison of pitch classes (modulus 12 of pitches) deduced from the input "raw" music with the input pitch classes of the underlying harmony/spectra (called tonalities here). All that would be needed technically is to instead allow for a comparison among pitches or MIDI note numbers instead (i.e. skipping the modulus 12 calculation). This behaviour could be the default or controlled with a keyword argument to tonality-map. Best, Torsten
  16. torstenanders

    sorting algorithms

    Simply slightly edit the algorithms below by inserting some additional output. Below I simply took one of the algorithms you linked and added a single print statement. If instead you want to collect all the results, then just accumulate them in some variable with a scope surrounding your algorithm function. (defun bubble-sort/naive (sequence) (let ((end (length sequence))) (labels ((compare-and-swap (index modified) ;; print intermediate results (print sequence) (if (= index (1- end)) (if modified (compare-and-swap 0 nil) (values)) (let ((index+1 (1+ index))) (if (> (elt sequence index) (elt sequence index+1)) (let ((x (elt sequence index))) (setf (elt sequence index) (elt sequence index+1) (elt sequence index+1) x) (compare-and-swap index+1 t)) (compare-and-swap index+1 modified)))))) (unless (< end 2) (compare-and-swap 0 nil)) sequence))) (bubble-sort/naive '(3 1 9 5 3 6 4 2 3 7)) Best, Torsten
  17. torstenanders


    Nice. You might like the graphical explanation of search algorithms and other algorithms at https://idea-instructions.com. They are visualising such algorithms basically following an IKAE style of graphics. Best, Torsten
  18. torstenanders

    Posting seed value

    Citing the documentation: "INIT-SEED can be used at the start of algorithmic compositions employing high degrees of randomness in order to create consisted results, without having to worry about supplying seed N values to all the other functions which may also use random generation." The function init-seed does not give you any new value actually (it just returns its argument), but in the background as a side-effect initialises the random generation of all Opusmodus random functions, so that their results are consistent on re-evaluation. Just try removing it in your function :) Besides, programs that reduce any changes to global states and side effects to the absolute minimum (which is most often using no stateful programming at all) are more easy to maintain and expand. Your little function introduces two stateful operations that are not needed here: setf (better use a local let) and init-seed. (This is even more important when writing concurrent code, which can be necessary when doing real-time stuff, e.g., when you have multiple processes running in parallel changing the same global variables without further precaution.) Best, Torsten
  19. torstenanders

    Posting seed value

    Below is a more secure variant of that function, which does not overwrite the seeds of all other functions. Calling init-seed is not needed here... I avoided using do in the function name, as functions/macros named such are by convention looping constructs. Best, Torsten (defun mk-seed (&optional seed) "Generates a random seed value, prints and returns it. Useful for exploring different results of random processes, but then keeping a found solution. Args: - seed (int): optionally fixes generated seed. Examples: (rnd-sample 3 '(c4 d4 e4) :seed (mk-seed)) ; 405621 rnd-sample => (c4 e4 d4) (rnd-sample 3 '(c4 d4 e4) :seed (mk-seed 13)) ; 13 rnd-sample => (e4 d4 e4) " (print (if seed seed (rnd-range 1 999999))))
  20. torstenanders

    Posting seed value

    > Perhaps if possible also with the variable name as a label to keep track of things when using several random functions in complex code: (setf bin-rhythm (gen-binary-rnd 5 5 2 1)) => bin-rhytm gen-binary-rnd :seed 37 This should be easy to do with a revision of the macro do-verbose, but as users, we have no access to its definition to change it. (The macro would check the value of the variable seed in its environment.) Side remark: If anyone revises do-verbose, it would be highly welcome to be able to switch off its effect altogether, because Common Lisp offers much better builtin debugging facilities than what this macro does. Anyway, here is an easy workaround for your particular situation. (setf bin-rhythm (gen-binary-rnd 5 5 2 1 :seed (print 123))) ; printed: 123 gen-binary-rnd => ((0 0 1 0 0) (1 0 1 0 1) (0 1 1 0 1) (1 1 0 1 1) (0 1 0 1 1)) See also the discussion in the thread linked below. Best, Torsten
  21. torstenanders

    Easiest way to add click track / Metronome in OM

    Wow, that is fancy :) Here is one that is even slightly more fancy, where the resulting softer velocity values also react to the velocity input, and also the pitch of easy beats is slightly different. (defun metronome (sequence &key (pitch 'c4) (velocity 90)) (let* ((ts (get-time-signature sequence)) (len (loop for i in ts collect (gen-repeat (car i) (list (/ 1 (second i)))))) (vel (loop for i in ts collect (append (get-velocity (list velocity) :type :symbol) (gen-repeat (1- (car i)) (get-velocity (list (- velocity 25)) :type :symbol))))) (pitch (loop for i in ts collect (cons pitch (pitch-transpose -2 (gen-repeat (1- (car i)) pitch)))))) (make-omn :length len :pitch pitch :velocity vel))) TA
  22. torstenanders

    Easiest way to add click track / Metronome in OM

    I suggest you simply and an explicit track to your score with repeated note values, e.g., quarter notes (crotchets), perhaps like the following. (make-omn :length (gen-repeat 16 '(1/4))) In your MIDI setup you may assign this to a percussive instrument, if you prefer. Best, Torsten
  23. torstenanders

    Opusmodus Vs. Symbolic Composer

    > If you open a midi-file created with Opusmodus with Logic, all the tracks will be created, the tempo map, the bar changes and logic will load instruments exactly as you describe. Yes, indeed. The only thing missing from Jor's list would be proper automation data, AFAIK. You can have CC data, but Logic automation data is a different animal. Best, Torsten
  24. torstenanders

    Opusmodus Vs. Symbolic Composer

    Are you talking about something different than MIDI realtime output to a DAW like Logic? What exactly do you mean by "compile a project to a DAW" that goes beyond MIDI routing? Best, Torsten