Jump to content


  • Content count

  • Joined

  • Last visited

  • Days Won


Everything posted by torstenanders

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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))))
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. I would like to define a new sound set to control a particular setting of the virtual organ GrandOrgue (https://sourceforge.net/projects/ourorgan/), a very nice and flexible pipe organ simulator. After investing quite some amount of time I now got some setting that allows me to nicely control GrandOrgue from Sibelius, and I would like to reproduce that control in Opusmodus. For that, I need to send certain CC messages and program change messages depending on articulations in the score. For example, I use articulations like 'I', to set the current staff to the organ division I (usually main) or 'II" for the division II (swell). Now, I might be simply missing something obvious here (e.g., a typo), but I keep getting error messages like the following when evaluating my sound set below this message, but I cannot find out what I am doing wrong. > Error: In sound set grandorgue-organ, program ped, there is no controller named: cc20 Can anyone perhaps see what I am missing here? Thanks a lot! Best, Torsten (def-sound-set GrandOrgue-organ :programs (:group couplers Ped (cc20 127) -Ped (cc20 1) I (cc21 127) -I (cc21 1) II (cc22 127) -II (cc22 1) III (cc23 127) -III (cc23 1) G_C (cc30 127) ;; sends program change messages to switch combinations for a certain division :group combinations P_1 1 P_2 2 P_3 3 P_4 4 P_5 5 P_6 6 P_7 7 P_8 8 P_9 9 P_10 10 I_1 21 I_2 22 I_3 23 I_4 24 I_5 25 I_6 26 I_7 27 I_8 28 I_9 29 I_10 30 II_1 41 II_2 42 II_3 43 II_4 44 II_5 45 II_6 46 II_7 47 II_8 48 II_9 49 II_10 50 III_1 61 III_2 62 III_3 63 III_4 64 III_5 65 III_6 66 III_7 67 III_8 68 III_9 69 III_10 70 ) :controllers (:group Default-Settings Pitch 0 Velocity-XF 2 Volume 7 Pan 10 Expression 11 Reverb-Dry/Wet 14 Reverb-On/Off 15 Slot-XF 20 Start-Scaler 21 Master-Attack 22 Master-Release 23 Master-Filter 24 Delay-Scaler 25 Tuning-Scaler 26 Humanize 27 Velocity-XF-On-Off 28 Rsamp-On-Off 29 Dynamics-Scaler 30 :group Pedal Pedal 64 ; not 'Ped' Sustain 64 Sost-Ped 66 Sostenuto 66 Una-Corda 67 Soft-Pedal 67 :group Matrix cc1 1 ))
  16. torstenanders

    Error: there is no controller named: cc20

    I see -- they need to be declared in in the :controllers section. Thanks a lot! I now got it almost working. Below is my current sound set again. I had to simplify the combination symbols to I1, I2 etc (the former underscore was confusing the OMN parser). What is missing still is support for combining articulations like II+II2 (i.e., use division II with combination 2 of that division). I can have combinations like stacc+II or leg+II2, but II+II2 is only notated, the playback does not work. Here are two examples. The first one works fine, but is not actually what I need. '((q c4 stacc+II) (e c4 leg d4 stacc e4 II4+leg f4 stacc) (q g4 marc -q -h)) The second example demonstrates the problem. '((q c4 II+II2) (e c4 leg d4 stacc e4 II4+leg f4 stacc) (q g4 marc -q -h)) Specifically, whether I notate II+II2 or II2+II, II is executed, but II2 is not. The later II4+leg again triggers the combination 4 fine. I had a look at a resulting exported MIDI file, and indeed in the combination II+II2 the CC message for II is output, but the program change message for II2 is not. If II2 or one of its friends is used independently or in a combination like stacc+II2 it does work, though. Is there perhaps some bug in the sound set definition here that only kicks in when user-defined articulations are combined? Thanks again! Best, Torsten PS: I only define support for predefined combinations of stops instead of stops directly for multiple reasons. This is more easy to define (less symbols overall), and is independent of specific organs or chosen stop combinations -- I can change the registration (combinations of stops used at certain moments) and even the organ without changing the score (generation). (add-text-attributes ;; Setting divisions and couplings ;; Note: I don't notate couplers with plus (e.g., I + II), but instead simply I and II ;; (Notation revised manually later in Sibelius) '(G_C "G.C.") '(Ped "Ped") '(I "I") '(II "II") '(III "III") '(-Ped "- Ped") '(-I "- I") '(-II "- II") '(-III "- III") ;; divisional combinations for the organ ;; ;; Pedal '(P1 "P: 1") '(P2 "P: 2") '(P3 "P: 2") '(P4 "P: 4") '(P5 "P: 5") '(P6 "P: 6") '(P7 "P: 7") '(P8 "P: 8") '(P9 "P: 9") '(P10 "P: 10") ;; ;; I '(I1 "I: 1") '(I2 "I: 2") '(I3 "I: 2") '(I4 "I: 4") '(I5 "I: 5") '(I6 "I: 6") '(I7 "I: 7") '(I8 "I: 8") '(I9 "I: 9") '(I10 "I: 10") ;; ;; II '(II1 "II: 1") '(II2 "II: 2") '(II3 "II: 2") '(II4 "II: 4") '(II5 "II: 5") '(II6 "II: 6") '(II7 "II: 7") '(II8 "II: 8") '(II9 "II: 9") '(II10 "II: 10") ;; ;; III '(III1 "III: 1") '(III2 "III: 2") '(III3 "III: 2") '(III4 "III: 4") '(III5 "III: 5") '(III6 "III: 6") '(III7 "III: 7") '(III8 "III: 8") '(III9 "III: 9") '(III10 "III: 10") ) ;;; TODO: uncomment when errors like "there is no controller named: cc20" are fixed (def-sound-set GrandOrgue-organ :programs (:group couplers Ped (cc20 127) -Ped (cc20 1) I (cc21 127) -I (cc21 1) II (cc22 127) -II (cc22 1) III (cc23 127) -III (cc23 1) G_C (cc30 127) ;; sends program change messages to switch combinations for a certain division :group combinations P1 1 P2 2 P3 3 P4 4 P5 5 P6 6 P7 7 P8 8 P9 9 P10 10 I1 21 I2 22 I3 23 I4 24 I5 25 I6 26 I7 27 I8 28 I9 29 I10 30 II1 41 II2 42 II3 43 II4 44 II5 45 II6 46 II7 47 II8 48 II9 49 II10 50 III1 61 III2 62 III3 63 III4 64 III5 65 III6 66 III7 67 III8 68 III9 69 III10 70 ) :controllers (:group Default-Settings Pitch 0 Velocity-XF 2 Volume 7 Pan 10 Expression 11 Reverb-Dry/Wet 14 Reverb-On/Off 15 Slot-XF 20 Start-Scaler 21 Master-Attack 22 Master-Release 23 Master-Filter 24 Delay-Scaler 25 Tuning-Scaler 26 Humanize 27 Velocity-XF-On-Off 28 Rsamp-On-Off 29 Dynamics-Scaler 30 :group Pedal Pedal 64 ; not 'Ped' Sustain 64 Sost-Ped 66 Sostenuto 66 Una-Corda 67 Soft-Pedal 67 :group Matrix cc1 1 cc20 20 cc21 21 cc22 22 cc23 23 cc30 30 ))
  17. torstenanders

    Playback of articulations

    It would be useful for playback, if certain articulations would affect the sounding note durations and velocity values. With some articulations this already seems to be the case (e.g., stacc seems to reduce note durations by 50%), while other articulations are ignored during playback in that regard (e.g., leg is notated, but makes seemingly no difference in playback -- notes played legato are not overlapping, as would be expected, nor are non-legato notes very slightly separated). Other articulations are seemingly even wrongly set (e.g., marc is an accent, but it instead shortens the note). Here is a little example demonstrating the problem, which results in the attached MIDI file. EDIT: The upload failed, but you can easily listening to this or export it to MIDI yourself. '((e c4 leg d4 e4 leg f4) (q g4 marc -q -h)) Can users somewhere set/correct these playback settings? BTW: Ideally settings would allow for code (functions) evaluationed on the fly. That would allow, e.g., to add custom humanisation, e.g., to slightly vary the length of staccato articuations, or the velocity values set by non-legato notes.... Thanks! Best, Torsten
  18. How is it possible to change the MIDI output channel of an instrument? For example, when writing for organ, you have two staffs for the right and left hand, but hands can change manuals, and this is best represented by different MIDI channels. Is there a way to define articulations that result in changing the MIDI channel? Thanks! Best, Torsten
  19. torstenanders

    Changing MIDI channels with articulations

    Thank you very much. Any chance to make legato notes slightly longer at a later stage? Doing so would trigger, e.g., certain orchestral libraries (e.g., I am using LASS) to play the legato articulations, which it does not play with non-legato notes. Best, Torsten
  20. torstenanders

    Changing MIDI channels with articulations

    It would also be useful, e.g., for combining sample instruments by different brands etc. where certain articulations are available in one plugin, and others in another. Best, Torsten
  21. torstenanders

    Changing MIDI channels with articulations

    If that is currently not possible then I can simply write unconventionally for different organ divisions directly for now. There is also a workaround with Hauptwerk using its so-called floating division MIDI keyboards (not sure about GrandOrgue yet). No worrries :) Best, Torsten
  22. You already know how to translate a MIDI pitch number into a representation consisting of two pieces of information, a pitch class integer and an octave integer. The conversion can be applied in both directions. Now, you can apply a similar conversion to a pitch class integers, converting them into a scale degree (integer) and an accidental (another integer), depending on a scale (a set of pitch classes). Again, this conversion can be done in both ways (there are multiple solutions if you allow for enharmonic equivalence). Once you have such a representation, you can then do diatonic transpositions (depending on whatever scale) within the scale degree domain, and finally translate your results back into pitch classes, or MIDI pitch numbers. I have a draft of a paper discussing this formally. A preliminary version of this paper has been published at SMC, http://uobrep.openrepository.com/uobrep/handle/10547/622264 Don't get scared away by the constraint programming aspect. Such conversions can also be implemented as plain deterministic functions. This can be seen as a kind of mapping, if you want, if you also see the relation between MIDI pitch numbers and pitch classes as a mapping :) Best, Torsten
  23. torstenanders

    Modulo 12 Function ?

    You can roll such a function easily yourself. The modulus function is part of Common Lisp. ;; modulus 12 of 60 (mod 60 12) ; => 0 (defun mod12 (xs) (loop for x in xs collect (mod x 12))) (mod12 '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 24 48)) ; => (0 1 2 3 4 5 6 7 8 9 10 11 0 1 2 3 4 5 6 7 0 0) To empower yourself, once you know how to program a simple function, you simply need to google for the modulus function http://lmgtfy.com/?q=common lisp modulo :) Best, Torsten
  24. torstenanders


    Does Opusmodus perhaps already have some quantisation function that expects a list of floats and that basically rounds these floats into a metric rhythm, including using tuplets? I am aware of vector-to-length – that implements a simple form of what I am looking for, but it does not support tuplets. Other algorithmic composition systems have more sophisticated quantisation facilities. For example, OpenMusic provides the box omquantify (among other functions in the Kant library). http://support.ircam.fr/docs/om/om6-manual/co/Quantification.html I am aware that quantification is a complex process, but perhaps that is already there in Opusmodus. Best, Torsten