Jump to content

torstenanders

Members
  • Posts

    496
  • Joined

  • Last visited

Posts posted by torstenanders

  1. Hi,

     

    Is there perhaps a way to adjust the overall duration of a nested (barred) OMN sequence? In particular, is there a function to cut notes etc. at the beginning/end of a sequence, so that the result has a specified overall duration?

     

    The first example just demonstrates what I would like to have.

    (setf phrase '((1/2 c4 1/4 d4) (1/4 e4 1/2 c4)))
    
    ;; Edit phrase such that the result is exactly 5/4 long by preserving the nesting structure
    (function-I-am-looking-for 5/4 phrase)
    ; => ((h c4 q d4) (q e4 c4)) 	; cut material at end
    ; => ((q c4 q d4) (q e4 h c4))  ; cut material at beginning

     

    There already exist at least two functions that are close, but not quite what I need. 

    ;; Does not keep nesting structure
    (length-span 5/4 phrase)
    ; => (h c4 q d4 e4 c4)
    ;; Adjusts individual sublists 
    (length-adjust 5/4 phrase)
    ; => ((h c4 q d4 -h) (q e4 h c4 -))

    Is there perhaps also a function that does what my example function-I-am-looking-for above does?

     

    Thanks a lot!

     

    Best,

    Torsten

     

  2. On 6/23/2020 at 3:10 PM, Avner Dorman said:

    Following up on this - is there a way to have Opusmodus work within a Jupyter notebook? I think it would be very useful in educational settings. I know there are lisp implementations that work in Jupyter:

     

    1104500?s=400&v=4
    GITHUB.COM

    An enhanced interactive Shell for Common Lisp (based on the Jupyter protocol) - fredokun/cl-jupyter

     

    - but is there a way to include Opusmodus as well? At least the functions and notation?

     

    If your goal is for you as a teacher to create documents for your students to read containing Common Lisp and Opusmodus code, and where you want to evaluate the code directly from within that document, then Org mode with embedded Common Lisp + Slime is your friend. This is a very powerful combination, that can automatically create nice slides (with the LaTeX beamer interface), embed music notation (Lilypond) etc. I used this combination for years for teaching, had then all sessions of a course in a single document for easily moving content around etc.

     

    Nevertheless, you likely do not want to introduce your students to use Org mode... For that, Jupyter notebooks (or plain Opusmodus) will be more easy for the students.

     

    ORGMODE.ORG

    Org: an Emacs Mode for Notes, Planning, and Authoring

     

     

    However, I don't know of a way to automatically embed music notation output of Opusmodus in Emacs Org mode. What is missing for that, AFAIK, is some Opusmodus function that automatically creates a graphic file for a given snippet or score. If that would be there, that feature shouldn't be too hard to add (other Org mode babel programming language interfaces do already similar things, e.g., Lilypond, and the code for that is freely available).

  3. The best document combining both worlds is likely the following. This was an internal textbook of the algorithmic composition teacher Paul Berg at the Sonology course at the Royal Conservatory of The Hague (the author of the composition system AC Toolbox, https://www.actoolbox.net), but it is unprinted, just a copy of a text processor document for internal use, and difficult to obtain (I only have a hard copy I got from a friend). 

     

    Berg, Paul (n.d.) Elements of Design. An introduction to Programming with Common Lisp. 
  4. http://www.gigamonkeys.com/book/

     

    LISP-LANG.ORG

    Books about Common Lisp

     

    For a more music-related introduction to Common Lisp you might want to look at the following books. These books teach algorithmic composition with Common Lisp. The above books introducing only Common Lisp are far more comprehensive on that matter, but you might prefer learning some foundations first within a  musical context.

     

     

    Morgan, N. & Legard, P. (2015) Parametric Composition: Computer-Assisted Strategies for Human Performance. West Yorkshire, UK: Tonality Systems Press.

    Introduces Opusmodus along with some Lisp.

     

     

    Taube, H. (2004) Notes from the Metalevel. London and New York: Taylor & Francis.
    This book introduces the algorithmic composition system Common Music, along with Lisp fundamentals.
     
     

    Algorithmic Composition: A Gentle Introduction to Music Composition Using Common LISP and Common Music

    https://quod.lib.umich.edu/s/spobooks/bbv9810.0001.001/1:3/--algorithmic-composition-a-gentle-introduction-to-music?rgn=div1;view=fulltext
    I have not read this one...
  5. Note that MOZ’Lib seemingly supports arbitrary libraries from the PatchWork / Open Music / PWGL family. Perhaps it is possible to see how they do that to add such functionality to Opusmodus as well? 

     

    Best,

    Torsten

     

    PS: I was working in a similar direction some time ago, first by porting some library (OM-Tristan) to load directly into a plain Lisp compiler (by replacing all OpusModus dependencies) and that works, but that is a lot of work for each library. I then started to instead port the whole of OpenMusic to ClozureCL, but leaving out all GUI dependencies, but got only half-way with that so far (it is a lot of code 🙂). Of course, if this works already in Julien's library, that would save some work... Unfortunately, I will not be able to take anything like this on in the foreseeable future due to my new job.

  6. Its a great development, but note that it will not work with Opusmodus for multiple reasons, one being that MOZ’Lib depends on SBCL [1], which is called from the shell, and Opusmodus depends on ClozureCL, and I don't think there are plans to make Opusmodus callable from a shell.

     

    [1] lisp-in-max-exploratory-computer-aided-c

  7. 49 minutes ago, opmo said:

    I am not getting any error with the expression.

     

    Just for the record, when I start Opusmodus without any of my extensions, I run into the same problem.

    ? (length-divide '(1000 2) '(q ab3 num1+leg c4 leg e ab3 leg g3 leg ab3 num1+leg c4 leg))
    length-divide, set: nil ignore: nil section: nil exclude: nil seed: 35424
    > Error: The value ab3 is not of the expected type sequence.
    > While executing: ccl::sequence-type, in process Listener-1(7).
    > Type cmd-. to abort, cmd-\ for a list of available restarts.
    > Type :? for other options.
    1 > 

     

  8. >  You will need to wait for the upgrade.

     

    No worries, I already applied a workaround (disabling certain code...).

     

    Here is another issue I ran into with length-divide: if the argument ignore is set to either min or max, and all note values are of the same length, then that also causes an error. Now, perhaps that should be expected, but then at least the error message could be more helpful. On the other hand, perhaps it would be preferable in this situation if a warning was printed and the effect of the argument ignore was, well, ignored? 

     

    (length-divide '(1 4) 
                   '(1/8 c4 mf num1+leg 1/8 d4 mf num1+leg 1/8 fs3 mf leg 1/8 gs3 mf)
                   :ignore 'min)
    Error: The value nil is not of the expected type number.
    

     

    > We have started work on microtonality  

    👍 

  9. Revising some older code of my I noticed that the function length-divide changed its behaviour somewhat and became more likely to cause an error.

     

    In a previous version, where the arguments count and divide where given separately, it was possible to set the count to some very high number, say, 1000, simply to mean that all notes the function can split (depending on its other arguments) will be split. 

     

    Meanwhile, the function have been revised to introduce control over intervals (thank you 🙂), but since then it seems it is not possible anymore to set an arbitrarily high count value anymore. For example, the following code now results in an error. I would prefer the previous behaviour, if only because it is more forgiving and stable.

     

    (length-divide '(1000 2) '(q ab3 num1+leg c4 leg e ab3 leg g3 leg ab3 num1+leg c4 leg))
    Error: The value ab3 is not of the expected type sequence.
    

     

    In case it helps: my debugger tells me the functions gen-repeat and then maybe-section are called (perhaps within a nested function of length-divide* ?) with an argument sequence bound to ab3 (i.e. a plain pitch), and a call (length ab3) then causes this error. 

     

    Thank you!

     

    Best,

    Torsten

  10. For a generic solution, you could use some function split-if that expects a Boolean function as argument comparing two consecutive pairs, and always splits a sublist if the Boolean function returns True. I don't have such a Lisp function at hand right now, but of an algorithm idea here is a similar Python function, only that this expects a Boolean function of a single argument only. If you port this function to Lisp, you could then generalise it by checking the number of arguments the given Boolean function expects, and it apply it always to the corresponding consecutive number of elements of xs.

     

    def split_if(fun, xs):
        """
        Splits `xs` (list) into sublists based on a test. Starts a new sublist
        at every element for which Boolean function `fun` returns true.
    
        Examples
        --------
    
        >>> split_if(lambda x: x % 3 == 0, [0, 1, 2, 3, 4, 5])
        [[0, 1, 2], [3, 4, 5]]
    
        >>> split_if(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7])
        [[1, 2], [3, 4, 5], [6, 7]]
    
        NOTE:
        Internally, `split_if` skips the first element of `xs`. So, if `fun` is
        stateful, it should initialise its state using that first element.
        For an example, see implementation of `format_api.split_into_sections`.
        """
        result_list = []
        start = 0
        # Collect new list up to x whenever fun(x) == true, but not before first element
        for index, x in enumerate(xs[1:]):
            if fun(x):
                result_list.append(xs[start:index+1])
                start = index+1
        if start == 0:
            return [xs]
        result_list.append(xs[start:])
        return result_list

     

     

    Here is another approach as well with a Lisp function from my toolbox expecting a list of positions where to split the list. You could find those positions by iterating over conservative pairs of your list elements with the function positions-if listed below.

     

    OK, none of this is a ready made solution, but all the necessary pieces are there 🙂  I need to head back to work now ....

     

    Torsten

     

    (defun subseqs (sequence positions &optional end)
      "Splits `sequence' into a list of subsequences split at `positions'. Each element in `positions' specifies a position at which a new sublist starts.
    
    ; (subseqs '(0 1 2 3 4 5 6) '(0 2 4))
    => ((0 1) (2 3) (4 5 6))
    
    ; (subseqs '(0 1 2 3 4 5 6) '(2 4 6) 5)
    => ((2 3) (4))
    
    `positions' are implicitly sorted and positions beyond end are excluded.
    "
      (let* ((updated-pos (sort (if end
    			       (remove-if #'(lambda (x) (>= x end))
    					  positions)
    			       positions)
    			    #'<))
    	(full-pos (append updated-pos
    			  (list (if end
    				    end
    				    (length sequence))))))
        (mapcar #'(lambda (start end)
    		(subseq sequence start end))
    	    (butlast full-pos)
    	    (rest full-pos))
        ))
        
       
    (defun positions-if (predicate sequence &key key (start 0))
      "Like the Common Lisp function `position-if', but returns all positions in `sequence' that match `predicate'.
    
    ; (positions-if #'oddp '((1) (2) (3) (4)) :key #'car)
    ; => (0 2)"
      (labels ((aux (predicate sequence &key key (start 0) accum)
    	     (let ((pos (position-if predicate sequence :start start :key key)))
    	       (if pos
    		   (aux predicate sequence :start (1+ pos) :key key :accum (cons pos accum))
    		   (reverse accum)))))
        (aux predicate sequence :start start :key key)))
    
    #|
    ;; comparison
    (position-if #'oddp '((1) (2) (3) (4)) :key #'car)
    |#
    
          

     

  11. if you have the article of ERES HOLZ as pdf, would be nice (the link seems to be dead)...

     

    See attached.

     

    > isn't it - in general - a question about complexity and information? 

     

    I think it is also a question of memory -- we can only perceive a form if we can remember the form parts (Schönberg talks about comprehensibility/Fasslichkeit) which then allows us to compare etc. Obviously, that is more easy in a visual form, where you can see the whole picture together and move between parts at your own pace.

     

    Best,

    Torsten

     

     Holz_2012_Das Wachstumprinzip von L-Systemen in der Musik von Hanspeter Kyburz.pdf

  12. the GAP is between visual L-systems and acoustic ones

     

    Yes, of course, there is a completely different way of perception at play. If you come up with a good answer to that, I would be interested.

     

    BTW, if you want some other examples of compositional applications, you might want to have a look at ”Cells” (1993/94) by Hanspeter Kyburz, discussed in the following two publications.

     

     

    Supper, M. (2001) A Few Remarks on Algorithmic Composition. Computer Music Journal. 25 (1), 48–53.

     

    Holz, E. (2012) Das Wachstumprinzip von L-Systemen in der Musik von Hanspeter Kyburz. Master’s thesis. Hochschule für Musik Hanns Eisler.  Available from: http://www.eresholz.de/de/text/Eres Holz_Ausschnitt aus der Masterarbeit.pdf(Accessed 20 September 2016).
     
  13. Just a brief follow-up. While Partch's book is obviously available in English, the other authors all wrote in German. More recent Neo-Riemannian theory is often pretty math-heavy, so also somewhat hard to digest for us composers. To get a taste of these harmonic theories in a highly developed form (with dualism throughout, but that is only one facet) delivered by a practicing composers, you might want to have a look at the recent English translation and discussion of Sigfrid Karg-Elert's book Acoustic Determination of Pitch, Chord and Function from 1930.

     

    Byrne, D. A. (2018) The Harmonic Theories of Sigfrid Karg-Elert: Acoustics, Function, Transformation, Perception. PhD Thesis thesis. University of Cincinnati. Online available (with a somewhat slow download speed) at https://etd.ohiolink.edu/apexprod/rws_olink/r/1501/10?p10_etd_subid=162928&clear=10
     
    Warning: this is not for the faint of heart 🙂
     
    Best,
    Torsten
  14. If you want more control over the L-system generation, have a look at the original documentation of the system L-Lisp, from which Janusz derived the Opusmodus functionality: 

     

    Erstad, K. A. (2002) L-systems, twining plants, Lisp. Master’s thesis thesis. University of Bergen. [online]. Available from: http://www.vcn.bc.ca/~griffink/lisp_lsystems.pdf
     
     
    Best,
    Torsten
  15. Are you simply looking for an invert function, e.g., pitch-invert? 

     

    (pitch-invert '(c4 d4 e4))
    => (c4 bb3 gs3)

     

    This function inverts (mirrors) around the first pitch by default. If you are looking for retaining the original ambitus, you might want to instead you my function invert-in-ambitus (https://tanders.github.io/tot/sources/pitch.html#_g251910).

     

    (invert-in-ambitus '(c4 e4 g4)) 
    => (g4 eb4 c4)


    BTW, when you are specifically talking about a harmonic context in which you are "mirroring" chords, there exist extensive music theories based on this idea already. The notion of minor chords as the mirror image of major chords, and its implications on harmonic functions (tonic, dominant, subdominant etc.) was in detail explored under the label of dualism by theorists like Hugo Riemann, Arthur von Öttingen and Sigfrid Karg-Elert. They also already generalised this notion for microtonal music. Likely independently of these theorists exploring the notion of dualism, Harry Partch's concept of otonality and utonality is also based on this idea, now firmly in the field of microtonal music. In microtonal harmonic theory I came across this notion also elsewhere (e.g., discussed by the composers and theorists of ekmelic music like Franz Richter Herf, which may have arrived there independently as well.

     

    Anyway, this harmonic concept in general is so basic and fundamental that I would not be surprised it would have been studied by the likes of Pythagoras already...

     

    Best,

    Torsten

  16. but SLEEP is not very precise

     

    The Common Lisp standard actually says that the number of seconds specified as arguments for sleep is approximate:

     

    > Causes execution to cease and become dormant for approximately the seconds of real time indicated by seconds, whereupon execution is resumed. 

     

    WWW.LISPWORKS.COM

     

    Anyway, it seems that at least on a Mac the imprecision is rather regular, see the following discussion with empirical tests.

    LISP-HUG.LISPWORKS.NARKIVE.COM

     

    Anyway, for realtime scheduling in a musical context one needs likely a proper scheduler for that. 

     

    Best,

    Torsten

  17. > Do you consider the inconsistency of the integer-to-pitch results a bug?

     
    I cannot speak for Janusz, but for me the format of the result makes sense. If there are individual values in the integer pitch list it is assume that the overall result is considered flat and hence sublists are chords. If everything is nested, then sublists are considered bars and the nesting is preserved.
     
    Best,
    Torsten
     
  18. > That is the main and most important point on the todo list i'm waiting for !

     

    I would also welcome this greatly, but I also understand that it might be tricky to realise when implemented from scratch, as MusicXML is a large standard.

     

    This project could become much much smaller when using some library that already has some  good MusicXML support. For example, one could use the pretty mature MusicXML import of music21 (http://web.mit.edu/music21/) and then use music21 + Python to generate OMN (e.g., an event list as output by Opusmodus' single-events). I did something similar once, that is rather easy to do and not such a big project. Python libraries can be called from Common Lisp using py4cl (https://github.com/bendudson/py4cl/). I tested py4cl in Opusmodus, it works. For example, all OMN generation could be done in a custom Python module, and py4cl is then used for just calling that. It seems the music21 licence would allow for that (https://github.com/cuthbertLab/music21/blob/master/music21/license.txt).

     

     

    Any Opusmodus user with a little bit of Python knowledge (which is rather easy for a Lisp programmer, see https://norvig.com/python-lisp.html) and some time could to that in principle 

    🙂

     

     

    Best,

    Torsten

     

×
×
  • Create New...

Important Information

Terms of Use Privacy Policy