Jump to content

AM

Members
  • Posts

    793
  • Joined

  • Last visited

Reputation Activity

  1. Like
    AM reacted to Deb76 in Opuspianotimbres for Pianoteq Video Contest 2017   
    Hello, 
    This is my participation at Pianoteq Video Contest 2017. The composition was written with Opusmodus and played in Ableton Live with seven instances of Pianoteq (modified TubularBells, modified ConcertArp recording, Steinway D Classical Recording A, modified Celesta, modified Cinbalom, modified original ChurchBells, Steinway D Classical Recording BA and completed with a Ircam Solo Instruments bank instance (flute, Horn, Cello) read via the UVI Workstation :
     
    and the list of videos in competition : http://www.forum-pianoteq.com/viewtopic.php?id=5301
    Do not hesitate to tell me what you think.
    Didier
    PS : It is advisable to play the video in 1080p HD and listen to the headphone for panoramic movements. 
  2. Like
    AM reacted to opmo in play with a specific delay   
    Yes it is possible on my dev system.
    I will see what I can do.
  3. Like
    AM reacted to torstenanders in Big Thank you to Torsten.   
    > If I can get OM, PWGL and Max to exchange data I am in kind of heaven.
     
    Having Opusmodus and PWGL exchanging data works easily via textfiles, but it is a bit awkward to set up (setting file names explicitly for each case etc.). I tried to "remove control" PWGL from Opusmodus with sockets etc., but could not get that working -- PWGL is not designed for that. 
     
    Getting PWGL libraries running within Opusmodus is a much more smooth connection, though the programming part tends to do a bit harder with plain Lisp code compared to PWGL patches (e.g., no objects or values to pick from menus). On the upside, the resulting programs are more concise and therefore more easy to read in Opusmodus compared with PWGL -- I prefer that :) 
     
    BTW: There is more in the pipeline.
     
    Best,
    Torsten
     
  4. Like
    AM reacted to Stephane Boussuge in articulation-map-omn   
    Here's a small function from my toolbox i use very often for adding articulation on already generated OMN material.
     
    Also useful for adding legato slurs.
     
    Link to video example:
     
     
    ;;; ============================================= ;;; ARTICULATION-MAP-OMN ;;; AJOUTE DES ARTICULATIONS SUR DES LISTES OMN ;;; BASÉES SUR DU PATTERN MATCHING. ;;; ============================================= (defun articulation-map-omn (map omn &key (otherwise '-)) (do-verbose ("articulation-map-omn") (let ((plist (disassemble-omn omn))) (setf (getf plist :articulation) (pattern-map map (getf plist :length) :otherwise otherwise :swallow t)) (apply 'make-omn plist)))) #| USAGE (setf mat '((q c4 p d4 e e4 f4 s g4 f a4 g4 f4 q e4) (e d4 mp c4 s d4 e4 f4 e4 q d4 e c4 b3) (h a3 f -h))) (setf prules '(((s s s) (leg leg leg)) ((s s) (leg leg)) ((s e) (- -)) ((s q) (- stacc)) ((q) (stacc)) ((e) (-)))) (setf out (articulation-map-omn prules mat)) |# SB.
  5. Like
    AM reacted to torstenanders in Collection of Opusmodus tools   
    Dear all,
     
    I released a collection of personal Opusmodus Tools at https://github.com/tanders/tot, together with installation instructions etc.
     
    Best,
    Torsten
  6. Like
    AM reacted to torstenanders in merge-voices on bar/beat   
    Thanks for sharing, this is a useful function. 
     
    However, I must say it took me some time to realise that this function is useful, because you did not provide any documentation. If I may say so, I would recommend you always document your functions, not only in the interest of potential other users, but in your own interest. Many years ago I developed a library over several months (a higher-level score language for the physical modelling synthesiser Tao, http://taopm.sourceforge.net) that helped me composing some piece. Some time later I wanted to use this library again, and was unable to do so, because of its lacking documentation -- I did not know how to use my own code anymore, and several months of work were effectively lost. Since then I am rather careful documenting my own work :)
     
    Because I like your function, I documented it myself for my own purposes (see doc string in the code block below). Please let me know if my documentation contains any misunderstandings. Also, please share if you are aware of any bugs.
     
    I am using this somewhat strange formatting of the doc string, because the library cldoc (https://gitlab.common-lisp.net/cldoc/cldoc/) can create some rather nice HTML doc files with this format. I tried a bunch of other doc generators, but cldoc worked best for me. In case you are interested in doc generators for your own work, cldoc's main downside is that internal and exported symbols are not distinguished (but also nested functions, e.g., global functions within flet are skipped). If you are looking for a doc generator, a useful overview is provided by https://sites.google.com/site/sabraonthehill/lisp-document-generation-apps.
     
    I also slightly changed your function for my purposes. I changed the name to merge-voices2, because that is slightly shorter. Perhaps more importantly, I changed your keyword arguments to plain arguments, because in my code I retain keyword arguments for named optional arguments, but the arguments of this function are not optional (there is no default value).
     
     Sincere apologies if I am sounding patronising. I just wanted to make this function more useful for myself, and perhaps also for others. 
     
    Best,
    Torsten
     
    (defun merge-voices2 (seq insert bar/beat) "Merges multiple monophonic lines resulting in a polyphonic part. Args: - seq (OMN sequence, must be nested): Voice to which other voices are added. The result retains the time signatures of SEQ. - insert (list of flat OMN sequences): Voices to merge into SEQ. Their time signatures are overwritten by the meter of SEQ. - bar/beat (list): List of start times of inserted sequences. Each INSERT start time is specified in the following format, where <bar-number> is a 1-based bar number (an int), <beat-number> is a 1-based beat number (an int), and <beat-subdivision> is the divisor for the beat number (also an int). ;;; (<bar-number> (<beat-number> <beat-subdivision>)) For example, (3 (2 4)) indicates the 2nd quarter note in the 3rd bar. Examples: Merge two OMN sequences. ;;; (merge-voices2 '((q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4)) ;;; '((q a4 a4 a4)) ;;; '((2 (2 8)))) Merge three sequences. ;;; (merge-voices2 '((q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4)) ;;; '((q b5 b5 b5) ;;; (e a4 a4 a4)) ;;; '((2 (2 8)) ;;; (3 (2 16)))) See also: The built-in function MERGE-VOICES is similar, but does not support shifting/offsetting added voices in time. " (car (last (let ((bar) (beat) (distance)) (progn (setf bar (loop for i in bar/beat collect (car i)) beat (loop for j in bar/beat collect (cadr j))) (loop for ba in bar for be in beat for ins in insert with time-sign = (get-time-signature seq) with ord-time-sign = (get-time-signature seq) do (setf time-sign (if (listp (car time-sign)) (loop for i in time-sign when (> (caddr i) 1) append (loop repeat (caddr i) collect (list (car i) (cadr i))) else collect (list (car i) (cadr i))) (append time-sign)) distance (if (listp (car time-sign)) (+ (sum (loop repeat (- ba 1) for i in time-sign collect (/ (car i) (cadr i)))) (/ (1- (car be)) (cadr be))) (+ (* (1- ba) (/ (car time-sign) (cadr time-sign))) (/ (1- (car be)) (cadr be))))) do (setf ins (append (list (neg! distance)) ins)) do (setf seq (omn-to-time-signature (length-rest-merge (flatten (merge-voices (omn-merge-ties seq) ins))) ord-time-sign)) collect seq do (setf time-sign ord-time-sign)))))))  
     
  7. Like
    AM got a reaction from torstenanders in merge-voices on bar/beat   
    (defun merge-voices** (seq &key insert bar/beat) (car (last (let ((bar) (beat) (distance)) (progn (setf bar (loop for i in bar/beat collect (car i)) beat (loop for j in bar/beat collect (cadr j))) (loop for ba in bar for be in beat for ins in insert with time-sign = (get-time-signature seq) with ord-time-sign = (get-time-signature seq) do (setf time-sign (if (listp (car time-sign)) (loop for i in time-sign when (> (caddr i) 1) append (loop repeat (caddr i) collect (list (car i) (cadr i))) else collect (list (car i) (cadr i))) (append time-sign)) distance (if (listp (car time-sign)) (+ (sum (loop repeat (- ba 1) for i in time-sign collect (/ (car i) (cadr i)))) (/ (1- (car be)) (cadr be))) (+ (* (1- ba) (/ (car time-sign) (cadr time-sign))) (/ (1- (car be)) (cadr be))))) do (setf ins (append (list (neg! distance)) ins)) do (setf seq (omn-to-time-signature (length-rest-merge (flatten (merge-voices (omn-merge-ties seq) ins))) ord-time-sign)) collect seq do (setf time-sign ord-time-sign))))))) (merge-voices** '((q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4)) :insert '((q a4 a4 a4)) :bar/beat '((2 (2 8)))) (merge-voices** '((q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4)) :insert '((q b5 b5 b5) (e a4 a4 a4)) :bar/beat '((2 (2 8)) (3 (2 16))))  
  8. Like
    AM got a reaction from hujairi in little stupid bot   
    an output-seq of "a little stupid bot" (works with stochastic broken-symmetrical elements and PM..)   - could produce for eternety (never ending)...  
    it works and i am going for holidays now 😀 
    greetings
    andré
     
       
  9. Like
    AM got a reaction from lviklund in little stupid bot   
    an output-seq of "a little stupid bot" (works with stochastic broken-symmetrical elements and PM..)   - could produce for eternety (never ending)...  
    it works and i am going for holidays now 😀 
    greetings
    andré
     
       
  10. Like
    AM got a reaction from opmo in little stupid bot   
    an output-seq of "a little stupid bot" (works with stochastic broken-symmetrical elements and PM..)   - could produce for eternety (never ending)...  
    it works and i am going for holidays now 😀 
    greetings
    andré
     
       
  11. Like
    AM reacted to torstenanders in Highly flexible envelopes: fenvs   
    In case someone is interested, I just put some of my libraries online. Fenv is a library of highly flexible envelopes for algorithmic composition. The software represents envelopes as numerical functions, called fenvs. It provides a rich set of functions to generate, combine and transform these envelopes.
     
    You can find the code at https://github.com/tanders/fenv, together with some information how to install and use.
     
    Best,
    Torsten
     
  12. Like
    AM reacted to torstenanders in Polyphonic preview?   
    I really like how Opusmodus allows to preview monophonic snippets (and other material, like interval sequences). No need to explicitly call some function or connect to some editor, as in other composition systems -- just use a keyboard shortcut to see and hear an intermediate result. However, what I miss is notating/auditioning intermediate results of polyphonic music with a single shortcut.  
     
    So, I defined the function preview-score, based on def-score. The function expects a polyphonic score in the slightly simplified format we discussed earlier. Here is a minimal example.
     
    (preview-score
     '(:vln ((q b4 a4 h g4))
       :vlc ((h g3 b3))))
     
    If I want to control further notation or playback parameters, preview-score provides arguments for that, but that is basically the same as using def-score directly. Instead, such parameters can be defined only once with global variables, and then used for multiple calls to preview-score. Here is some example setting.
     
    (setf *default-preview-score-instruments*
      '(:vln (:program 'violin :sound 'gm)
        :vlc (:program 'cello :sound 'gm)))
    (defparameter *default-preview-score-header*
      '(:title "Opus magnum"
        :tempo 80))
     
    Janusz: How can I define a keyboard shortcut that calls the function preview-score with the score returned by a selected code region (or the Lisp expression just before the cursor)? Thanks! 
     
    For completeness, the definition of preview-score is below. 
     
    Best,
    Torsten
     
    ;;; just some dummy settings for now (defparameter *default-preview-score-instruments* '(:vln (:program 'violin :sound 'gm) :vlc (:program 'cello :sound 'gm)) "Settings for each instrument used by `preview-score'. The format is a plist where keys are the instrument labels, and values a list with the actual settings. For format of these settings are the same as instrument settings for `def-score' with keywords like :sound, :channel etc. -- except for they key :omn.") ;;; just some dummy settings for now (defparameter *default-preview-score-header* '(:title "Opus magnum" :tempo 80) "Global score settings used by `preview-score'. The format is a plist where keys are the instrument labels, and values a list with the actual settings. The format is the same as the header settings for `def-score' with keywords like :title, :key-signature etc.") (defun preview-score (score &key (name 'test-score) (instruments *default-preview-score-instruments*) (header *default-preview-score-header*)) "Notates and plays a score in a format slightly simpler than expected by def-score, i.e., without its header. Args: - score (plist): a headerless score. See below for its format. - name (symbol): The score name. - instruments (plist): Keys are instrument labels, and values a list with the actual settings. These settings have the same format as instrument settings for `def-score' with keywords like :sound, :channel etc. -- except for they key :omn. - header (plist): The format is the same as the header settings for `def-score' with keywords like :title, :composer, :key-signature etc. Score format: ;;; (<part1-name-keyword> <part1-OMN> ;;; <part2-name-keyword> <part2-OMN> ;;; ...) Example: ;;; (preview-score ;;; '(:vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5)) ;;; :vlc ((q g3) (q c4 b3 a3 g3) (h. c3))) ;;; :instruments '(:vln (:program 'violin :sound 'gm) ;;; :vlc (:program 'cello :sound 'gm)) ;;; :header '(:title \"Opus magnum\" ;;; :tempo 80)) " ;; Using eval is problematic (https://stackoverflow.com/questions/2571401/why-exactly-is-eval-evil/), ;; but hard to avoid for a dynamically created def-score expression that requires splicing with ,@. ;; Possible alternative would be to define preview-score as macro, but then arguments are not evaluated. (eval `(def-score ,name ;; quote all header args, because symbol values must be quoted... ,(mapcar #'(lambda (x) `',x) (append header ;; add default vals of required header args at end -- they are overwritten by args given (list :key-signature 'atonal ;; By default, use implicit time signature of 1st part :time-signature (om:get-time-signature (second score)) :tempo 70))) ,@(mapcar #'(lambda (part) (let ((part-symbol (first part)) (part-omn (second part))) (list* part-symbol :omn `(quote ,part-omn) (getf instruments part-symbol)))) (plist->pairs score))) ) (audition-musicxml-last-score) *last-score*) #| ; mini test (preview-score '(:vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5)) :vlc ((q g3) (q c4 b3 a3 g3) (h. c3))) :instruments '(:vln (:program 'violin :sound 'gm) :vlc (:program 'cello :sound 'gm)) :header '(:title "Opus magnum" :tempo 80)) |#  
  13. Like
    AM reacted to Wim Dijkgraaf in Out-of-the-box algorithms   
    Hi AM,
     
    A couple of months ago I followed some online courses on http://www.kadenze.com . Especially the generative art courses as well as The Nature Of Code course. So I started wondering which of the techniques form those courses are supported by standard Opusmodus functions. 
     
    That brought me to the idea to make a list of those topics and eventually also have a couple of links to online and free material with inspiring explanations and background info.
     
    Kind regards,
     
    Wim
  14. Like
    AM got a reaction from opmo in post processing with bar/beat   
    dear janusz
     
    what do you think about the idea(s) to work with "bar/beat" for post-processing the scores. i see that's - in my momentary work - very useful...
    for example: insert at bar/beat, cut-out bar/beat/span, overwrite bar/beat, pattern-matching bar/beat/span ... ?
     
    by the way i'm coding a little bit on a function which gets me the positions of perhaps a pattern-match (single values and patterns), in the format (bar (beat)), for example (1 (3 4)), but it's not so simple... (a lot of specialities, and i can't put it into ONE code)
     
    ...
     
    greetings
    andré
     
     
  15. Like
    AM got a reaction from opmo in overwriting   
    i think, it works like that :-)
     
    now, you could OVERWRITE you original OMN sequentially with inserts... (it's very useful for "post-production" of your generated score!). 
    i have changed the input-format (bar/beat), and it also works with changing time-signatures... i know, janusz or the opmp-programmers could code it smarter, but my concept/code seems to work... so take it and optimize it!!!
     
    greetings
    andré
    p.s. when wil be approx. the release of vers 2 of OPMO?
     
    ;;; OVERWRITING (defun get-resolution2 (be) (cond ((member (cadr be) '(3 6 12 24 48)) 1/24) ((member (cadr be) '(1 2 4 8 16 32)) 1/16) ((member (cadr be) '(5 10 20 40)) 1/20) ((member (cadr be) '(7 14 28 56 1)) 1/28))) (defun overwrite (seq &key insert bar/beat) (car (last (let ((bar) (beat) (resolution) (distance)) (progn (setf bar (loop for i in bar/beat collect (car i)) beat (loop for j in bar/beat collect (cadr j))) (loop for ba in bar for be in beat for ins in insert with time-sign = (get-time-signature seq) with ord-time-sign = (get-time-signature seq) do (setf resolution (get-resolution2 be) time-sign (if (listp (car time-sign)) (loop for i in time-sign when (> (caddr i) 1) append (loop repeat (caddr i) collect (list (car i) (cadr i))) else collect (list (car i) (cadr i))) (append time-sign)) distance (if (listp (car time-sign)) (+ (sum (loop repeat (- ba 1) for i in time-sign collect (/ (/ (car i) (cadr i)) (get-resolution2 be)))) (/ (/ (1- (car be)) (cadr be)) (get-resolution2 be))) (+ (/ (* (1- ba) (/ (car time-sign) (cadr time-sign))) (get-resolution2 be)) (/ (/ (1- (car be)) (cadr be)) (get-resolution2 be))))) do (setf seq (omn-to-time-signature (length-rest-merge (omn-merge-ties (flatten (loop repeat (length (omn-to-time-signature seq (list (numerator resolution) (denominator resolution)))) for cnt = 0 then (incf cnt) with new-seq = (omn-to-time-signature seq (list (numerator resolution) (denominator resolution))) with ins-rounded = (append ins (rest (length-rational-quantize (list (apply '+ (omn :length ins))) :round resolution))) when (= cnt distance) collect ins-rounded and do (setf cnt (+ (/ (get-span (flatten ins-rounded)) resolution) cnt -1)) else collect (nth cnt new-seq))))) ord-time-sign)) do (setf time-sign ord-time-sign) collect seq)))))) ;;; EXAMPLES: ;;; with changing time-signatures (overwrite '((e c6 a5 h b5 q tie) (q b5 b5 a5 tie) (q a5 q a5) (h. g5)) :insert '((3q c5 b4 bb4 a4) (3q c4 b3 bb3 a3)) :bar/beat '((1 (2 12)) (3 (1 12)))) ;;; with constant time-signature (overwrite '((e c6 a5 h b5 tie) (q b5 b5 a5 tie) (h a5 q a5) (h. g5)) :insert '((3q c5 b4 bb4 a4) (3q c4 b3 bb3 a3)) :bar/beat '((1 (7 12)) (3 (2 12))))  
     
  16. Like
    AM reacted to torstenanders in Nested tuplet?   
    Does Opusmodus already support the notation of nested tuplets?
     
    Nested tuplets are easily expressed directly with fractions. For example, for the nested rhythm found at 
    http://klangnewmusic.weebly.com/direct-sound/lets-talk-rhythm-part-2-nested-tuplets 
    I can write the following. 
     
    '(2/15 2/15 2/15 2/25 2/25 2/25 2/25 2/25 1/20 3/20)
     
    The playback of this rhythm works fine, but the notation is unnecessarily complex. Not even the simple time signature 2/4 is detected. 
     
    Also, I could not find the length symbols for the required durations. For example, what is the symbol for the fraction 2/15? 
     
    Thanks! 
     
    Best,
    Torsten
  17. Like
    AM got a reaction from Stephane Boussuge in get-position (add for "inserting-on..."-function   
    ;;; gets the position => bar and beat where the value is ;;; => could be used in combination with "inserting-on-bar/beat*", ;;; if you are looking for a specific value to sprout a sequqnce ;;; FUNCTION (defun get-position (seq value &key (get 'all)) (let ((beat) (bar (car (loop for i in seq for bar = 1 then (incf bar) append (loop for j in (single-events i) when (pattern-matchp j (list value)) collect bar))))) (progn (setf beat (loop for k in (loop for i in (single-events (nth (1- bar) seq)) when (not (pattern-matchp i (list value))) append (omn :length i) else collect 'match) when (numberp k) collect (abs k) into bag when (equal k 'match) do (return (list (1+ (numerator (abs (sum bag)))) (denominator (abs (sum bag)))))))) (cond ((equal get 'all) (list bar beat)) ((equal get 'bar) (append bar)) ((equal get 'beat) (append beat))))) ;;; EXAMPLES: (setf seq '((h c4 q q) (e f4 pp f4 mp f4) (-3q 3q cs5 -3q h))) (get-position seq 'cs5 :get 'all) (get-position seq 'cs5 :get 'bar) (get-position seq 'cs5 :get 'beat) (get-position seq 'pp :get 'all)  
  18. Like
    AM got a reaction from Yuichi Yamamoto in inserting a sequence by overwriting   
    hi all
     
    the following function could be usefull, it's a first sketch, but it seems to work....
     
    if you want to INSERT a new OMN-seq, perhaps in bar 2 on the 3/20 in your BASIC-OMN-sequence... with this function you can do this, it will overwrite your original phrase.
    test it or tell me whatelse would be better...
     
    greetings
    andré
     
    ;;; ------------------------------------------------------------------------ ;;; INSERTING SEQ BY OVERWRITING ;;; ------------------------------------------------------------------------ ;;; SUB (defun get-resolution2 (beat) (cond ((memberp (cadr beat) '(3 6 12 24 48)) 1/24) ((memberp (cadr beat) '(1 2 4 8 16 32)) 1/16) ((memberp (cadr beat) '(5 10 20 40)) 1/20) ((memberp (cadr beat) '(7 14 28 56)) 1/28))) ;;; MAIN: INSERTING SEQ BY OVERWRITING (defun inserting-on-bar/beat* (seq &key insert time-sign bar beat) (let ((resolution (get-resolution2 beat)) (ord-time-sign time-sign) (time-sign (if (listp (car time-sign)) (loop for i in time-sign when (> (caddr i) 1) append (loop repeat (caddr i) collect (list (car i) (cadr i))) else collect (list (car i) (cadr i))) (append time-sign))) (distance (if (listp (car time-sign)) (+ (car (loop repeat (- bar 1) for i in time-sign collect (/ (* (1- bar) (/ (car i) (cadr i))) (get-resolution2 beat)))) (/ (/ (1- (car beat)) (cadr beat)) (get-resolution2 beat))) (+ (/ (* (1- bar) (/ (car time-sign) (cadr time-sign))) (get-resolution2 beat)) (/ (/ (1- (car beat)) (cadr beat)) (get-resolution2 beat)))))) (omn-to-time-signature (omn-merge-ties (flatten (loop repeat (length (omn-to-time-signature seq (list (numerator resolution) (denominator resolution)))) for cnt = 0 then (incf cnt) with new-seq = (omn-to-time-signature seq (list (numerator resolution) (denominator resolution))) with insert-rounded = (append insert (rest (length-rational-quantize (list (apply '+ (omn :length insert))) :round resolution))) when (= cnt distance) collect insert-rounded and do (setf cnt (+ (/ (get-span (flatten insert-rounded)) resolution) cnt -1)) else collect (nth cnt new-seq)))) ord-time-sign))) ;;; EXAMPLES (inserting-on-bar/beat* '((e c6 a5 h b5 tie) (q b5 b5 a5 tie) (h a5 q a5) (h. g5)) :insert '(s f3 e3 eb3 d3) :time-sign '(3 4) :bar 2 :beat '(2 16)) (inserting-on-bar/beat* '((e c6 a5 h b5 tie) (q b5 b5 a5 tie) (h a5 q a5) (h. g5)) :insert '(3q c5 b4 bb4 a4) :time-sign '(3 4) :bar 1 :beat '(2 12)) ;;; EXAMPLE WITH different TIME-SIGNATURES (inserting-on-bar/beat* '(e c6 a5 h b5 tie q b5 b5 a5 tie h a5 q a5 h. g5) :insert '(5q c5 b4 bb4 a4) :time-sign '((2 4 1) (3 8 1) (5 8 1) (3 4 1)) :bar 3 :beat '(3 20))  
  19. Like
    AM reacted to RST in Parataxis for chamber ensemble   
    Hello people!
     
    This is a relatively recent work that I composed with Opusmodus.  A septet...
    Alto Flute, Clarinet, Trombone, Viola, Violoncello, Piano, Percussion
    This is a live recording from the premiere at the Trieste Prima Festival and is by Ensemble MD7 conducted by Steven Loy.
     

  20. Like
    AM reacted to opmo in Opusmodus 1.2.22292   
    New: FILTER-EVENTS
     
    The function FILTER-EVENTS internally brakes-up an omn sequence into single-events (l p v a) and checks whether an event contains the given element. When an element is found the event is returned. All other events are transformed into rests. The option remain will invert the process.
    (filter-events 'd4 '(e c4 mp -e fermata e. d4 -h e. c4 e e4)) => (-q e. d4 mp -h.s) (filter-events 'd4 '(e c4 mp -e fermata e. d4 -h e. c4 e e4) :remain t) => (e c4 mp -e fermata -he. e. c4 e e4)  
    These two options are useful for orchestration.
     
    Examples:
    (setf mat1 '(e c4 mp arco+ponte -e fermata e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto)) (filter-events 'arco+ponte mat1) => (e c4 mp arco+ponte -we) (filter-events 'arco+ponte mat1 :remain t) => (-e -e fermata e. d4 mp tasto -h e. c4 p pizz+ponte e e4 arco+tasto) (filter-events 'fermata mat1 :remain t) => (e c4 mp arco+ponte - e. d4 tasto -h e. c4 p pizz+ponte e e4 arco+tasto) (filter-events 'fermata mat1) => (-e -e fermata -w) (filter-events 'd4 mat1 :remain t) => (e c4 mp arco+ponte -e fermata -he. e. c4 p pizz+ponte e e4 arco+tasto) (filter-events '(e d4) mat1) => (e c4 mp arco+ponte - e. d4 tasto -he. e e4 p arco+tasto) (filter-events '(e d4) mat1 :remain t) => (-e -e fermata -he. e. c4 p pizz+ponte -e) (setf mat2 '((e c4 mp arco+ponte -e fermata e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) (e c4 f stacc e. d4 -h e. c4 p ord -e fermata e4 stacc))) (filter-events 'e. mat2 :section 1 :remain t) => ((e c4 mp arco+ponte -e fermata e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) (e c4 f stacc -h.. -e fermata e4 p stacc)) (filter-events '((e.) (e4 fermata)) mat2) => ((-q e. d4 mp tasto -h e. c4 p pizz+ponte -e) (-w -e fermata e4 p stacc)) (filter-events '(e4 fermata) mat2 :remain t) => ((e c4 mp arco+ponte - e. d4 tasto -h e. c4 p pizz+ponte -e) (e c4 f stacc e. d4 -h e. c4 p ord -q)) Best wishes,
    JP
  21. Like
    AM reacted to opmo in Opusmodus 1.2.22215   
    New functions:
    HALF-SINE, HALF-SAWTOOTH, HALF-TRIANGLE, HALF-SQUARE
    JOIN-ATTRIBUTES, DISJOIN-ATTRIBUTES
     
    HALF-SINE  
    The HALF-SINE function generates a sequence of vectors that describe and simulate the characteristics of a half sine wave.
     
    First the GEN-SINE:
    (gen-sine 32 1 0.5)  

     
     
    Now the HALF-SINE:
    (half-sine 32 0.5)  

     
     
    With control over resolution (the length of the wave), frequency and amplitude (and additional control over phase and modulation) this function can be a remarkably effective tool for creating gestural forms in pitch, rhythm, dynamics and structure.
     
    Examples:
     
    With the shortcut ⌃1 (menu: Plot/Numbers) as a guide it's possible to experiment with shapes and forms before applying these to musical parameters.
     
    (half-sine 120 1.0 :phase 90)  

     
     
    In the example below the keyword :modulation is applied and its values are generated by the GEN-SINE function.
    (half-sine 120 1.0 :phase 90 :modulation (gen-sine 120 1 0.2))  

     
     
    In the example below the amplitude parameter '(0.5 0.2 0.1) has three values. These represent a sequence of alternating amplitudes.
    (half-sine 120 '(0.5 0.2 0.1))  

     
     
    In this final example the keyword :phase is used to produce a different start point (90) in the 360 degree range.
    (half-sine 120 '(0.5 0.2 0.1) :phase 90)  

     
     
    In this final example the GEN-SINE the amplitude values are generated by the HALF-SINE function:
    (gen-sine 120 5 (half-sine 120 1.0 :phase 180))  

     
    (gen-sine 120 5 (half-sine 240 1.0 :phase 180))  

     
     
    Here below there's a clear example of how alternating amplitude values can affect the wave output when the vectors are mapped to pitches.
    (vector-to-pitch '(g3 g5)  (gen-sine 120 32 (half-sine 120 1.0 :phase 180))  
     

     
     
     
    HALF-TRIANGLE  
    The HALF-TRIANGLE function generates a sequence of vectors that describe and simulate the characteristics of a half triangle wave.
     
    First the GEN-TRIANGLE:
    (gen-triangle 32 1 0.5)  

     
     
    Now the HALF-TRIANGLE:
    (half-triangle 32 0.5)  

     
    With control over resolution (the length of the wave), frequency and amplitude (and additional control over phase and modulation) this function can be a remarkably effective tool for creating gestural forms in pitch, rhythm, dynamics and structure.
     
    Examples:
     
    With the shortcut ⌃1 (menu: Plot/Numbers) as a guide it's possible to experiment with shapes and forms before applying these to musical parameters.
     
    (half-triangle 120 1.0 :phase 45)  

     
     
    In the example below the keyword :modulation is applied and its values are generated by the GEN-TRIANGLE function.
    (half-triangle 120 1.0 :phase 45 :modulation (gen-triangle 120 1 0.2))  

     
     
    In the example below the amplitude parameter '(0.5 0.2 0.1) has three values. These represent a sequence of alternating amplitudes.
    (half-triangle 120 '(0.5 0.2 0.1))  

     
     
    In this final example the keyword :phase is used to produce a different start point (90) in the 360 degree range.
    (half-triangle 120 '(0.5 0.2 0.1) :phase 90)  

     
     
    In this final example the GEN-TRIANGLE the amplitude values are generated by the HALF-TRIANGLE function:
    (gen-triangle 120 5 (half-triangle 120 1.0 :phase 180))  

     
    (gen-triangle 120 5 (half-triangle 240 1.0 :phase 180))  

     
     
    Here below there's a clear example of how alternating amplitude values can affect the wave output when the vectors are mapped to pitches.
    (vector-to-pitch '(g3 g5)  (gen-triangle 120 32 (half-triangle 120 1.0 :phase 180))  
     

     
     
     
    HALF-SQUARE  
    The HALF-SQUARE function generates a sequence of vectors that describe and simulate the characteristics of a half square wave.
     
    First the GEN-SQUARE:
    (gen-square 32 1 0.5)  

     
     
    Now the HALF-SQUARE:
    (half-square 32 0.5)  

     
     
    With control over resolution (the length of the wave), frequency and amplitude (and additional control over phase and modulation) this function can be a remarkably effective tool for creating gestural forms in pitch, rhythm, dynamics and structure.
     
    Examples:
     
    With the shortcut ⌃1 (menu: Plot/Numbers) as a guide it's possible to experiment with shapes and forms before applying these to musical parameters.
     
    (half-square 120 1.0 :phase 45)  

     
     
    In the example below the keyword :modulation is applied and its values are generated by the GEN-SQUARE function.
    (half-square 120 1.0 :phase 90 :modulation (gen-square 120 1 0.7))  

     
     
    In the example below the amplitude parameter '(0.5 0.2 0.1) has three values. These represent a sequence of alternating amplitudes.
    (half-square 120 '(0.5 0.2 0.1))  

     
     
    In this final example the keyword :phase is used to produce a different start point (90) in the 360 degree range.
    (half-square 120 '(0.5 0.2 0.1) :phase 90)  

     
     
    In this final example the GEN-SQUARE the amplitude values are generated by the HALF-SQUARE function:
    (gen-square 120 5 (half-square 120 1.0 :phase 180))  

     
    (gen-square 120 5 (half-square 240 1.0 :phase 180))  

     
     
    Here below there's a clear example of how alternating amplitude values can affect the wave output when the vectors are mapped to pitches.
    (vector-to-pitch '(g3 g5)  (gen-square 120 32 (half-square 120 1.0 :phase 180))  
     

     
     
     
    HALF-SAWTOOTH  
    The HALF-SAWTOOTH function generates a sequence of vectors that describe and simulate the characteristics of a half sawtooth wave.
     
    First the GEN-SAWTOOTH:
    (gen-sawtooth 32 1 0.5)  

     
     
    Now the HALF-SAWTOOTH:
    (half-sawtooth 32 0.5)  

     
     
    With control over resolution (the length of the wave), frequency and amplitude (and additional control over phase and modulation) this function can be a remarkably effective tool for creating gestural forms in pitch, rhythm, dynamics and structure.
     
    Examples:
     
    With the shortcut ⌃1 (menu: Plot/Numbers) as a guide it's possible to experiment with shapes and forms before applying these to musical parameters.
     
    (half-sawtooth 120 1.0 :phase 90)  

     
     
    In the example below the keyword :modulation is applied and its values are generated by the GEN-SAWTOOTH function.
    (half-sawtooth 120 1.0 :phase 90 :modulation (gen-sawtooth 120 1 0.7))  

     
     
    In the example below the amplitude parameter '(0.5 0.2 0.1) has three values. These represent a sequence of alternating amplitudes.
    (half-sawtooth 120 '(0.5 0.2 0.1))  

     
     
    In this final example the keyword :phase is used to produce a different start point (90) in the 360 degree range.
    (half-sawtooth 120 '(0.5 0.2 0.1) :phase 90)  

     
     
    In this final example the GEN-SAWTOOTH the amplitude values are generated by the HALF-SAWTOOTH function:
    (gen-sawtooth 120 5 (half-sawtooth 120 1.0 :phase 180))  

     
    (gen-sawtooth 120 5 (half-sawtooth 240 1.0 :phase 180))  

     
     
    Here below there's a clear example of how alternating amplitude values can affect the wave output when the vectors are mapped to pitches.
    (vector-to-pitch '(g3 g5)  (gen-sawtooth 120 32 (half-sawtooth 120 1.0 :phase 180))  
     

     
     
     
    DISJOIN-ATTRIBUTES
    The function DISJOIN-ATTRIBUTES separates a combined articulations into a list of its individual attributes.
     
    (disjoin-attributes 'leg+ponte) => (leg ponte) (disjoin-attributes 'leg+ponte+stacc) => (leg ponte stacc)  
     
    JOIN-ATTRIBUTES
    The function JOIN-ATTRIBUTES merges a list of attributes into one articulation.
     
    (join-attributes '(leg ponte)) => leg+ponte  (join-attributes '(leg+ponte stacc)) => leg+ponte+stacc  
      Fix to OMN-REPLACE :articulation   Best wishes, JP
  22. Like
    AM reacted to torstenanders in create/read extended single-events   
    >  in my view it would be nice to EXTEND the "make-omn/single-events"-structure by x-add-datas...
     
    Yes, I was wishing for that as well for some time -- I designed extendable music representations myself for other applications before... 
     
    However, meanwhile I understand that this is not really possible nor desirable for Opusmodus. The current OMN format is already rather flexible (kind of a language), that already allows for pretty much arbitrary symbols as articulations, and articulation combinations (as single symbol joined with +). Allowing for an arbitrary number of symbols as articulations or other data would make parsing (detecting note boundaries) much harder, or would require that OMN would do what many other music representations out there are doing: that individual notes are represented as separate data elements (e.g., separate lists, as output by single-events). Such a representation would be less concise -- you would less want to directly type it by hand anymore. Either approach to extensions would also break very many existing functions.  
     
    The good news is that by merging multiple articulations in a single articulation symbol you do not need to break the existing functionality, and can still have all the extensibility you need. The only restrictions are that an articulation is always a symbol that has been declared as such before (e.g., numerical data is a bit tricky here, yes). 
     
    Beyond that, nothing stops you from rolling you own music representation in whatever format you want, but you may want then to always have two additional functions that transform your format into the OMN format and back :)
     
    > b) in my way i see completely transparent and easy what's up, and not a mixture of text-attributes/data...?
     
    Multiple articulations combined in a single symbol are well readable, I would say -- something that cannot always be said of, say, object-oriented data abstractions of other algorithmic composition systems. I would argue that together with functions such as merge-articulations and disassemble-articulations that I defined above, you can see this as a data abstraction [1], which is extendable. 
     
    > c) if I could change the OPMO SINGLE-EVENTS-structure, i would extend it like I did ...and not mixing it, isnt' it much more "logic" (but perhaps not for a programmer-brain :-))
     
    In principle there is not really much of a difference between these two positions here, it is up to you to decide. The main downside of your custom format is that you loose all direct interoperability with OMN functions and functionality (e.g., snippet preview), but occasionally the advantages will be outweighing such downsides. In this particular case the only advantage of your approach that I see is that you can (more easily) add numerical data.  
     
    > a) isn't it better to "seperate" the BASIC-OMN-structure from the additionals? in a way, i'm more independet if OPMO changes some things?
     
    That is better answered by Janusz.
     
    Best,
    Torsten 
     
    [1] https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-13.html#%_chap_2, chapter in Abelson, H. et al. (1985) Structure and Interpretation of Computer Programs. Cambridge, MA: MIT Press; a book that is extremely useful for every Lisp programmer, though it uses the Lisp dialect Scheme.
     
  23. Like
    AM reacted to torstenanders in create/read extended single-events   
    Here is a revision
     
    (defun make-corresponding-rest (event) "Turns a single OMN note into a rest of the same note value. Rests remain rests, and rest articulations are preserved. Example: (make-corresponding-rest '(h c4))" (let ((len (omn-encode (first event)))) (cons ;; rests should remain rests (if (> len 0) (* len -1) len) (omn :rest-articulation event)))) (defun insert-articulation (flat-omn-list &rest articulations) "Merge in one or more lists of articulations to an OMN expression. Example: ;; added nil for the rest (extended-single-events '(e c4 mp arco e. d4 -h e. p pizz e e4 arco) '(ponte tasto nil ponte tasto)) => (e c4 mp arco+ponte e. d4 mp tasto -h e. d4 p pizz+ponte e e4 p arco+tasto) BUG: does not skip rests. Wait for omn-replace supports composite articulations to fix" (apply #'append (loop for event in (single-events flat-omn-list) for data in (matrix-transpose optional-data) when (length-notep (first event)) collect (let ((event-art (fourth event))) (append (subseq event 0 3) (list (merge-articulations (if event-art (cons event-art data) data))))) else collect event))) #| ;; automatic orchestration application (add-text-attributes '(trp "trp") '(fl "fl") '(clar "clar")) (extended-single-events '(e c4 mp stacc e. d4 -h e. c4 p ord e e4 stacc) '(trp fl trp trp fl clar) '(flt tr1 tr2 flt tr1 tr2)) ; => '(e c4 mp stacc+trp+flt e. d4 mp fl+tr1 -h e. c4 p ord+trp+flt e e4 p stacc+fl+tr1) |# (defun filter-note-parameters (flat-omn-list parameter &key (remove-non-matching? nil)) "Checks every note whether it contains `parameter'. All notes containing the parameter are preserved, all other notes are turned into rests. If a note contains a combination of articulations, all of them are checked. Args: flat-omn-list: flat OMN list parameter: a length, pitch, OMN velocity or single articulation remove-rests? (default nil): if true, all notes that do not match are removed instead of turned into rests. Examples: (filter-note-parameters '(e c4 mp arco+ponte e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) 'e.) => (-1/8 e. d4 mp tasto -1/2 e. c4 p pizz+ponte -1/8) (filter-note-parameters '(e c4 mp arco+ponte e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) 'arco) => (e c4 mp arco+ponte -3/16 -1/2 -3/16 e e4 p arco+tasto) (filter-note-parameters '(e c4 mp arco+ponte e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) 'arco :remove-non-matching? T) => (e c4 mp arco+ponte e e4 p arco+tasto) " (remove :not-matching (apply #'append (loop for event in (single-events flat-omn-list) when (and (length-notep (first event)) (member (omn-encode parameter) (append (list (omn-encode (first event))) (subseq event 1 3) (disassemble-articulations (fourth event))))) collect event else collect (if remove-non-matching? '(:not-matching) (make-corresponding-rest event)))))) #| ;; continue automatic orchestration application (filter-note-parameters '(e c4 mp stacc+trp+flt e. d4 mp fl+tr1 -h e. c4 p ord+trp+flt e e4 p stacc+fl+tr1) 'trp) ; => (e c4 mp stacc+trp+flt -3/16 -1/2 e. c4 p ord+trp+flt -1/8) (filter-note-parameters '(e c4 mp stacc+trp+flt e. d4 mp fl+tr1 -h e. c4 p ord+trp+flt e e4 p stacc+fl+tr1) 'e.) |#
  24. Like
    AM reacted to torstenanders in Towards algorithmic orchestration (and customising sound playback with multiple sound libraries)   
    Dear Alain Jamot, 
     
    here is a function that may help you. This function is useful for customising sound playback with multiple sound libraries or for algorithmic orchestration. 
     
    The function expects an OMN expression and returns a list of multiple OMN sequences (multiple parts). It basically sorts notes from the OMN sequence into different parts, depending on the articulations of individual notes. All notes with certain articulations go in one resulting parts, and notes with other articulations in another part.
     
    Here is an example. It sorts all notes with pizz or arco articulations into one part, and notes with trem articulations into another part. Each time, notes are substituted by rests in other parts, so that timing relations of notes in different parts are preserved.  
    (separate-parts '((h c4 pizz q arco) (h trem q h pizz) (h arco+stacc -q fermata))                 '((pizz arco)                   (trem))) => ; part 1: pizz and arco    ((h c4 mf pizz q arco) (-h q c4 mf h pizz) (h c4 mf arco+stacc -q fermata))    ; part 2: trem    ((-h -q) (h c4 mf trem -q -h) (-h -q fermata)))  
    You can then assign your first part to on MIDI channel in your def-score call, and the next part to another MIDI channel, e.g., like so.
    (setf omn-expr '((h c4 pizz q arco) (h trem q h pizz) (h arco+stacc -q fermata))) (setf parts (separate-parts omn-expr                             '((pizz arco)                               (trem)))) (def-score two-violins            (:title "Title"             :composer "Composer"             :copyright "Copyright © "             :key-signature 'chromatic             :time-signature '((1 1 1 1) 4)             :tempo 100             :layout (bracket-group                      (violin1-layout 'violin1)                      (violin2-layout 'violin2)))      (violin1    :omn (nth 0 parts)    :channel 1    :sound 'gm    :program 'violin    :volume 100    :pan 54    :controllers (91 '(48))    )      (violin2    :omn (nth 1 parts)    :channel 2    :sound 'gm    :program 'violin    :volume 100    :pan 74    :controllers (91 '(60))    )   )  
    The function definition of separate-parts is below.
     
    Best,
    Torsten
     
    Janusz: This is another example of a function showing how processing polyphonic music with double-nested OMN expressions can be useful. Once we have a standard notation for polyphonic OMN expressions with multiple voices/parts in Opusmodus 2, as discussed earlier, then this function can easily be adapted to output that format. 
    (labels ((make-corresponding-rest (event) (let ((len (omn-encode (first event)))) (cons ;; rests should remain rests (if (> len 0) (* len -1) len) (omn :rest-articulation event)))) (push-event-and-rests (event matching-position result-omns articulation-sets-length) (push event (nth matching-position result-omns)) (loop for i in (remove matching-position (gen-integer 0 (1- articulation-sets-length))) do (push (make-corresponding-rest event) (nth i result-omns))))) (defun separate-parts (sequence articulation-sets) "The function `separate-parts' is useful for customising your sound playback with multiple sound libraries or for algorithmic orchestration. The function breaks an OMN sequence (a single part) into a list of multiple OMN sequences (multiple parts). It basically sorts notes from the OMN sequence into different parts, depending on the articulations of individual notes. All notes with certain articulations go in one resulting parts, and notes with other articulations in another part. In all other resulting parts, notes are substituted by rests, so that timing relations of notes in different parts are preserved. This function can be useful, when you have multiple sound libraries that support different articulations of the same instrument. You can then perform notes with certain articulations on one software instrument (on its own MIDI channel etc.), and notes with other articulations on another instrument. Alternatively, you can use the function for algorithmic orchestration, where you assign custom articulations (typically declared with add-text-attributes first) such as instrument labels with your custom algorithm, and then use this function in a second step to separate your instruments. Remember that the result of this function is a list of multiple OMN sequences (multiple parts). You have to split it into its individual parts for use in OMN. Args: - sequence: OMN sequence, can be nested - articulation-sets: list of list of articulations. All notes with articulations contained in the first articulation-set end up in the first resulting part, notes with articulations in the second set end up in the second part and so forth. The decision which part a note belongs to is always made based on the first articulation that matches an articulation-set. If a note contains no articulation, or an articulation contained in no set, then it is matched to the first articulation-set. If an articulation is contained in multiple articulation-sets, then the earlier match in articulation-sets is used. Examples: (separate-parts '(h c4 pizz q arco) '((pizz) (arco))) => ((h c4 mf pizz -q) ; part 1 with pizz articulations (-h q c4 mf arco)) ; part 2 with arco (separate-parts '((h c4 pizz q arco) (h trem q h pizz) (h arco+stacc -q fermata)) '((pizz arco) (trem))) => (((h c4 mf pizz q arco) (-h q c4 mf h pizz) (h c4 mf arco+stacc -q fermata)) ; part 1: pizz and arco ((-h -q) (h c4 mf trem -q -h) (-h -q fermata))) ; part 2: trem " (if (listp (first sequence)) ;; sequence is nested (matrix-transpose (mapcar #'(lambda (seq) (separate-parts seq articulation-sets)) sequence)) ;; sequence is flat list (let* ((articulation-sets-length (length articulation-sets)) (result-omns (make-list articulation-sets-length :initial-element nil))) (loop for event in (single-events sequence) do (let ((event-articulation (fourth event))) (if event-articulation (let ((matching-position (position-if #'(lambda (articulation-set) (some #'(lambda (art) (member art (disassemble-articulations event-articulation))) articulation-set)) articulation-sets))) (if matching-position (push-event-and-rests event matching-position result-omns articulation-sets-length) ;; if no match, then add event to first omn result (push-event-and-rests event 0 result-omns articulation-sets-length))) ;; if no articulation, then add event to first omn result (push-event-and-rests event 0 result-omns articulation-sets-length)))) (mapcar #'(lambda (result) (flatten-omn (reverse result))) result-omns))))) ;; for your convenience, I include the following definition already shared earlier (defun disassemble-articulations (art) "Splits a combined OMN articulations into a list of its individual attributes. Example: (disassemble-articulations 'leg+ponte) => (leg ponte)" (mapcar #'intern (split-string (symbol-name art) :separator "+")))
  25. Like
    AM reacted to torstenanders in Klangfarbenmelodie   
    As you likely already know, what you can do in a single voice/part is specifying various articulations, which can result in different timbres of your playback, including user-defined specifications with the function def-sound-set. Beyond that, you could split your part into multiple parts, in the score, where each is performed by its own MIDI channel (basically reproducing how a Klangfarbenmelodie would be realised in an orchestra setting). The advantage of expressing different timbres of different instruments with multiple parts is that it allows for dove-tailing, where the last note of one instrument and the first note of the next are shared by both for a better connecting. 
     
    Anyway, if you want to generate only a single part with timbre specifications, why not defining a function that allows to split it into multiple parts for the orchestra later. I proposed such a function for your convenience at 
     
     
    Best,
    Torsten
     
×
×
  • Create New...

Important Information

Terms of Use Privacy Policy