Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 01/03/2015 in all areas

  1. 6 points
    RST

    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.
  2. 5 points
    opmo

    Opusmodus 1.2.22703

    New function: TIME-SWALLOW and minor bug fixes. The function TIME-SWALLOW 'swallows' sequence of pitches derived from the divide of every length value of a sequence by a given time value: (/ 1/2 1/16) = 8. The rest-lengths are omitted. (setf length '(1/2 1/16 7/16 1/8 3/8 3/16 5/16 1/4 1/4 5/16 3/16 3/8)) (setf infinity (infinity-series 100 '(g4 gs4))) => (g4 gs4 fs4 a4 gs4 g4 f4 bb4 fs4 a4 g4 gs4 a4 fs4 e4 b4 gs4 g4 f4 bb4 g4 gs4 fs4 a4 f4 bb4 gs4 g4 bb4 f4 eb4 c5 fs4 a4 g4 gs4 a4 fs4 e4 b4 g4 gs4 fs4 a4 gs4 g4 f4 bb4 a4 fs4 e4 b4 fs4 a4 g4 gs4 e4 b4 a4 fs4 b4 e4 d4 cs5 gs4 g4 f4 bb4 g4 gs4 fs4 a4 f4 bb4 gs4 g4 bb4 f4 eb4 c5 g4 gs4 fs4 a4 gs4 g4 f4 bb4 fs4 a4 g4 gs4 a4 fs4 e4 b4 f4 bb4 gs4 g4) (time-swallow 1/16 1 length pitch) => (g4 fs4 a4 gs4 f4 f4 g4 fs4 a4 g4 g4 a4) Time 1/16 in each length: 8 1 7 2 6 3 5 4 4 5 3 6 8 1 7 2 g4 gs4 fs4 a4 gs4 g4 f4 bb4 fs4 a4 g4 gs4 a4 fs4 e4 b4 gs4 g4 6 3 5 4 f4 bb4 g4 gs4 fs4 a4 f4 bb4 gs4 g4 bb4 f4 eb4 c5 fs4 a4 g4 gs4 4 5 3 6 a4 fs4 e4 b4 g4 gs4 fs4 a4 gs4 g4 f4 bb4 a4 fs4 e4 b4 fs4 a4 Example with swallow :type 1 (default) and with chord-size (3 3 2 1): (make-omn :length length :pitch (time-swallow 1/16 '(3 3 2 1) length pitch)) => (h g4gs4fs4 s fs4a4g4 q.. a4g4 e gs4 q. f4bb4g4 e. f4bb4gs4 qs g4bb4 q fs4 a4fs4e4 qs g4gs4fs4 e. g4f4 q. a4) 8-3 1-3 7-2 2-1 g4 gs4 fs4 a4 gs4 g4 f4 bb4 fs4 a4 g4 gs4 a4 fs4 e4 b4 gs4 g4 6-3 3-3 5-2 4-1 f4 bb4 g4 gs4 fs4 a4 f4 bb4 gs4 g4 bb4 f4 eb4 c5 fs4 a4 g4 gs4 4-3 5-3 3-2 6-1 a4 fs4 e4 b4 g4 gs4 fs4 a4 gs4 g4 f4 bb4 a4 fs4 e4 b4 fs4 a4 Same as above but with swallow :type 2: (make-omn :length length :pitch (time-swallow 1/16 '(3 3 2 1) length pitch :type 2)) => (h g4gs4fs4 s g4gs4a4 q.. fs4e4 e gs4 q. a4f4bb4 e. c5fs4a4 qs a4fs4 q fs4 f4bb4a4 qs fs4a4g4 e. fs4b4 q. cs5) 8-3 1-3 7-2 g4 gs4 fs4 a4 gs4 g4 f4 bb4 fs4 a4 g4 gs4 a4 fs4 e4 b4 gs4 g4 f4 bb4 g4 2-1 6-3 3-3 gs4 fs4 a4 f4 bb4 gs4 g4 bb4 f4 eb4 c5 fs4 a4 g4 gs4 5-2 4-1 4-3 a4 fs4 e4 b4 g4 gs4 fs4 a4 gs4 g4 f4 bb4 a4 fs4 e4 b4 5-3 3-2 6-1 fs4 a4 g4 gs4 e4 b4 a4 fs4 b4 e4 d4 cs5 gs4 g4 f4 bb4 g4 More examples: (make-omn :length length :pitch (time-swallow 'e '(3 3 2 1) length pitch)) => (h g4gs4fs4 s gs4g4f4 q.. gs4g4 e fs4 q. a4g4gs4 e. a4fs4e4 qs e4b4 q gs4 f4bb4g4 qs g4gs4fs4 e. fs4a4 q. f4) (make-omn :length length :pitch (time-swallow 'e '(3 3 2 1) length pitch :type 2)) => (h g4gs4fs4 s f4bb4fs4 q.. fs4a4 e fs4 q. e4b4gs4 e. bb4g4gs4 qs a4f4 q gs4 bb4f4eb4 qs fs4a4g4 e. a4fs4 q. b4) (setf length2 (gen-length (distributive-cube (interference2 '(3 2))) '(1/16))) => ((1/2 1/4 1/4 1/2 1/4 1/8 1/8 1/4 1/4 1/8 1/8 1/4 1/2 1/4 1/4 1/2) (1/4 1/8 1/8 1/4 1/8 1/16 1/16 1/8 1/8 1/16 1/16 1/8 1/4 1/8 1/8 1/4) (1/4 1/8 1/8 1/4 1/8 1/16 1/16 1/8 1/8 1/16 1/16 1/8 1/4 1/8 1/8 1/4) (1/2 1/4 1/4 1/2 1/4 1/8 1/8 1/4 1/4 1/8 1/8 1/4 1/2 1/4 1/4 1/2)) (make-omn :length length2 :pitch (time-swallow '(3e e s) '((3 3 2 1) (2 3)) length2 pitch)) => ((h g4gs4fs4 q a4fs4e4 f4bb4 h f4 q a4fs4e4 e fs4a4gs4 g4f4 q a4 g4gs4e4 e b4e4d4 cs5gs4 q f4 h f4bb4gs4 q gs4g4f4 g4gs4 h f4) (q g4gs4 e fs4a4gs4 a4gs4 q gs4g4f4 e f4bb4 s bb4fs4a4 bb4fs4 e bb4fs4a4 fs4a4 s a4g4gs4 a4g4 e a4g4gs4 q g4gs4 e a4fs4e4 fs4e4 q e4b4gs4) (q g4gs4fs4 e gs4g4f4 f4bb4 q fs4 e a4fs4e4 s e4b4gs4 b4gs4 e gs4 f4bb4g4 s g4gs4fs4 gs4fs4 e fs4 q f4bb4gs4 e bb4f4eb4 eb4c5 q fs4) (h g4gs4 q a4fs4e4 f4bb4 h f4bb4gs4 q a4fs4 e fs4a4gs4 g4f4 q a4fs4e4 g4gs4 e b4e4d4 cs5gs4 q f4bb4g4 h f4bb4 q gs4g4f4 g4gs4 h f4bb4gs4)) (make-omn :length length2 :pitch (time-swallow '(3e e s) '((3 3 2 1) (2 3)) length2 pitch :type 2)) => ((h g4gs4fs4 q e4b4gs4 fs4a4 h f4 q gs4fs4a4 e fs4e4b4 g4gs4 q a4 gs4g4f4 e f4bb4gs4 f4eb4 q gs4 h bb4fs4a4 q gs4fs4a4 a4g4 h gs4) (q g4gs4 e a4gs4g4 f4bb4 q fs4a4g4 e a4fs4 s e4b4gs4 gs4g4 e g4f4bb4 g4gs4 s fs4a4f4 f4bb4 e bb4gs4g4 q bb4f4 e c5fs4a4 g4gs4 q a4fs4e4) (q g4gs4fs4 e f4bb4fs4 g4gs4 q fs4 e g4f4bb4 s gs4fs4a4 f4bb4 e gs4 bb4f4eb4 s fs4a4g4 gs4a4 e fs4 q b4g4gs4 e g4f4bb4 fs4e4 q fs4) (h g4gs4 q fs4e4b4 gs4fs4 h bb4f4eb4 q fs4a4 e fs4e4b4 g4gs4 q a4fs4b4 f4bb4 e bb4gs4g4 eb4c5 q fs4a4gs4 h g4gs4 q a4gs4g4 gs4a4 h f4bb4g4)) JP
  3. 5 points
    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.
  4. 5 points
    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 "+")))
  5. 5 points
  6. 5 points
    Stephane Boussuge

    Fibonacci's Meditation

    An ambient piece based on a Fibonacci series. SB. FibonacciMeditation.opmo
  7. 4 points
    opmo

    Opusmodus 1.2.22733

    Extended documentation and bug fix in do-timeline and do-timline2 functions if binary list.
  8. 4 points
    Hello, Following the 2017 Pianoteq contest, I was surprised to be ranked 4th in the contest and get a special prize with this little piece written with Opusmodus. Didier http://www.forum-pianoteq.com/viewtopic.php?id=5373
  9. 4 points
    opmo

    Opusmodus 1.2.22714

    Fix to DO-TIMELINE and DO-TIMELINE2 functions when with T or NIL plus minor bug fixes.
  10. 4 points
    opmo

    DADA Quartet

    Algorithmic avant garde jazz improvisation for tenor saxophone, piano, bass and drums. I thought it is time to add something new to our 'Made in Opusmodus' forum. Samples: VSL Ensemble Pro with Vienna Instruments Pro. If you like to study the score, here it is: DADA Quartet.opmo
  11. 4 points
    Deb76

    DADA Quartet

    Dear Janusz, Here is a first result from a series of pitches based on "Mi Myxolydien" (a mix with the notes of Amazing Grace version Judy Collins and Third Stone from the Sun by Jimi Hendrix) insert in Def-Library. I recorded the IAC tracks in Ableton Live in the arrangement window and since I do not have an interesting jazz saxophone, I split the tracks and the piano so I could get some changes to the timbres. Besides the bass, the piano and the drums, I used three sessions of Softube modular synthesizer, Modular, including one with the Buchla 259e module (the somewhat space-like sound and which sometimes emphasizes the piano) and two instruments of the Korg Gadget suite for Mac, the Arp Odyssey emulation and the Wave Station emulation in a synthetic brass sound). Didier
  12. 4 points
    torstenanders

    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. 4 points
    torstenanders

    Out-of-the-box algorithms

    > more high-level algorithms I cannot answer your question concerning built-in algorithms, but if you are looking for further ideas what could be added, here is some related literature. A good general overview of algorithmic composition techniques, from a technical point of view. Nierhaus, G. (2009) Algorithmic Composition: Paradigms of Automated Music Generation. Wien, New York: Springer. Discussions of compositional applications in OpenMusic (likewise implemented in Common Lisp, though the main interface is a visual language) by various composers. Agon, C. et al. (eds.) (2006) The OM Composer’s Book. 1. Delatour France. Bresson, J. et al. (eds.) (2008) The OM Composer’s Book. 2. Editions Delatour France / Ircam. Hirs, R. & Gilmore, B. (eds.) (2009) Contemporary Compositional Techniques and OpenMusic. Collection Musique/Sciences. IRCAM/Delatour. Bresson, J. et al. (eds.) (2016) The OM Composer’s Book . 3. Paris; Sampzon: Editions Delatour France. Most of you likely already know the book by Nigel Morgan, containing discussions of compositional applications in Opusmodus itself. Morgan, N. & Legard, P. (2015) Parametric Composition: Computer-Assisted Strategies for Human Performance. West Yorkshire, UK: Tonality Systems Press. The perhaps most important algorithmic composition technique of Common Music (also implemented in common Lisp) and SuperCollider are patterns / item streams, which can be nested. http://commonmusic.sourceforge.net/cm/res/doc/cm.html#patterns Taube, H. (2004) Notes from the Metalevel. London and New York: Taylor & Francis. Online: http://www.moz.ac.at/sem/lehre/lib/cm/Notes from the Metalevel/00/contents.html The libraries of the venerable PatchWork and its successors PWGL and OpenMusic (all Common Lisp) provide ideas for various approaches, some already mentioned above. Below are links to relevant link collections. OpenMusic libraries: http://repmus.ircam.fr/openmusic/libraries PWGL libraries: http://www2.siba.fi/pwgl/downloads.html Another successful technique, implemented in multiple PWGL and OpenMusic libraries and beyond is constraint programming. I did a lot of research in this area and therefore quote some own publication here. Anders, T. & Miranda, E. R. (2011) Constraint Programming Systems for Modeling Music Theories and Composition. ACM Computing Surveys. 43 (4), 30:1–30:38. Online: https://pdfs.semanticscholar.org/7d0e/783e5bb1c35a871a45e72fddaf7bf3db5d28.pdf. Of course, there is much more literature on algorithmic composition (computer-aided composition) out there, but the above literature gives a good starting point to study more general composition techniques and their applications. Best, Torsten
  14. 4 points
    opmo

    Looking for a function that could do that

    (apply #'mapcar #'list '((1 3 5) (2 4 6)))
  15. 4 points
    opmo

    Opusmodus 1.2.22097

    Some changes to the Text & Lyrics tools. If you used one of them please check the new functions. The text-to-pitch function is replaced with TEXT-MAP with more options and functionality. text-map map text &key flat rnd-order otherwise seed [Function] Arguments and Values: map a list of lists (<letter><symbol>) text a string, a string list list of a list of letters. flat T or NIL. The default is T. rnd-order T or NIL. The default is NIL. otherwise Nil, symbol or list of symbols. The default is NIL. seed an integer - ensure the same result each time the code is evaluated. The default is NIL. Description: This function converts a body of text into any symbol (parameter). It’s a further way to use words ("text") or a list of letters to create parametric material. Notice, that the function creates lists for each word and that punctuation is ignored. In the following examples we will map a text to integers. First we create a map: (defparameter *map-integer1* '(((a à á â ã ä å æ ą) 0) (b 1) ((c ç ć) 2) (d 3) ((e è é ê ë ę) 4) (f 5) (g 6) (h 7) ((i ì î ï) 8) (j 9) (k 10) ((l ł) 11) (m 12) ((n ñ ń) 13) ((o ò ó ô õ ö) 14) (p 15) (q 16) (r 17) ((s ś) 18) (t 19) ((u ù ú û ü) 20) (v 21) (w 22) (x 23) ((y ý ÿ) 24) ((z ż ź) 25))) (setf text '("To be, or not to be, that is the question")) (text-map *map-integer1* text) => ((19 14) (1 4) (14 17) (13 14 19) (19 14) (1 4) (19 7 0 19) (8 18) (19 7 4) (16 20 4 18 19 8 14 13)) In the following map each letter is mapped into a list of two integer values. The letter (a à á â ã ä å æ ą) is mapped to 0 and -12. Every time the letter (a à á â ã ä å æ ą) is processed, 0 or -12 integer is picked at random. (defparameter *map-integer2* '(((a à á â ã ä å æ ą) (0 -12)) (b (1 -1)) ((c ç ć) (2 -2)) (d (3 -3)) ((e è é ê ë ę) (4 -4)) (f (5 -5)) (g (6 -6)) (h (7 -7)) ((i ì î ï) (8 -8)) (j (9 -9)) (k (10 -10)) ((l ł) (11 -11)) (m (12 -12)) ((n ñ ń) (13 -13)) ((o ò ó ô õ ö) (14 -14)) (p (15 -15)) (q (16 -16)) (r (17 -14)) ((s ś) (18 -18)) (t (19 -19)) ((u ù ú û ü) (20 -20)) (v (21 -21)) (w (22 -22)) (x (23 -23)) ((y ý ÿ) (24 -24)) ((z ż ź) (25 -25)))) (text-map *map-integer2* text) => ((19 -14) (-1 -4) (14 17) (-13 -14 -19) (-19 -14) (1 4) (19 7 0 -19) (-8 18) (19 -7 -4) (-16 20 -4 -18 19 8 -14 -13)) (text-map *map-integer2* text) => ((-19 14) (1 -4) (-14 17) (13 14 19) (19 14) (1 4) (19 7 0 19) (8 18) (19 -7 -4) (16 20 4 18 -19 8 -14 -13)) A seed will ensure the same result each time the code is evaluated: (text-map *map-integer2* text :seed 48) => ((19 -14) (1 -4) (14 -14) (-13 -14 19) (19 -14) (-1 4) (19 7 -12 -19) (8 18) (-19 -7 4) (16 -20 -4 18 19 -8 -14 -13)) In the following examples we map a text to lengths. If a letter is mapped to a nested list ((e e. s)) then the entire list is selected. (defparameter *map-length* '(((a à á â ã ä å æ ą) ((s s s))) (b ((s e s))) ((c ç ć) ((e s s))) (d ((s s e))) ((e è é ê ë ę) ((e e. s))) (f ((q e. s))) (g ((e. e s))) (h ((q s s))) ((i ì î ï) ((s e. e))) (j ((s e. e))) (k ((s s q))) ((l ł) ((e s e.))) (m ((e e e))) ((n ñ ń) ((e q e))) ((o ò ó ô õ ö) ((q e e))) (p ((e e q))) (q ((q q. e))) (r ((h q. e))) ((s ś) ((q e q.))) (t ((h e e))) ((u ù ú û ü) ((e q. q))) (v ((q. e h))) (w ((e e h))) (x ((q e q.))) ((y ý ÿ) ((q q q))) ((z ż ź) ((q h q))))) (text-map *map-length* text) => ((h e e q e e) (s e s e e. s) (q e e h q. e) (e q e q e e h e e) (h e e q e e) (s e s e e. s) (h e e q s s s s s h e e) (s e. e q e q.) (h e e q s s e e. s) (q q. e e q. q e e. s q e q. h e e s e. e q e e e q e)) (text-map *map-length* text :flat nil) => ((h e e) (q e e) (s e s) (e e. s) (q e e) (h q. e) (e q e) (q e e) (h e e) (h e e) (q e e) (s e s) (e e. s) (h e e) (q s s) (s s s) (h e e) (s e. e) (q e q.) (h e e) (q s s) (e e. s) (q q. e) (e q. q) (e e. s) (q e q.) (h e e) (s e. e) (q e e) (e q e)) With the rnd-order option we can randomise the order of the elements in the list: (text-map *map-length* text :flat nil :rnd-order t) => ((h e e) (q e e) (s e s) (s e. e) (e e q) (h e q.) (e q e) (e q e) (h e e) (h e e) (e q e) (s e s) (s e e.) (e h e) (q s s) (s s s) (e e h) (e. e s) (q. q e) (e h e) (s q s) (s e e.) (q. e q) (q. e q) (s e e.) (q q. e) (e h e) (s e e.) (e q e) (e e q)) In the following examples we map text to pitches. First we create a simple map with a letter mapped to a single pitch: (defparameter *map-pitch1* '(((a à á â ã ä å æ ą) c3) (b cs3) ((c ç ć) d3) (d eb3) ((e è é ê ë ę) e3) (f f3) (g fs3) (h g3) ((i ì î ï) gs3) (j a4) (k bb3) ((l ł) b3) (m c4) ((n ñ ń) cs4) ((o ò ó ô õ ö) d4) (p eb4) (q e4) (r f4) ((s ś) fs4) (t g4) ((u ù ú û ü) gs4) (v a4) (w bb4) (x b4) ((y ý ÿ) c5) ((z ż ź) cs5))) (text-map *map-pitch1* text) => ((g4 d4) (cs3 e3) (d4 f4) (cs4 d4 g4) (g4 d4) (cs3 e3) (g4 g3 c3 g4) (gs3 fs4) (g4 g3 e3) (e4 gs4 e3 fs4 g4 gs3 d4 cs4)) Here we map a letter to a list of two pitches: (defparameter *map-pitch2* '(((a à á â ã ä å æ ą) (c4 c3)) (b (cs4 b3)) ((c ç ć) (d4 bb3)) (d (eb4 a3)) ((e è é ê ë ę) (e4 gs3)) (f (f4 g3)) (g (fs4 fs3)) (h (g4 f3)) ((i ì î ï) (gs4 e3)) (j (a4 eb3)) (k (bb4 d3)) ((l ł) (b4 cs3)) (m (c5 c3)) ((n ñ ń) (cs5 b2)) ((o ò ó ô õ ö) (d5 bb2)) (p (eb5 a2)) (q (e5 gs2)) (r (f5 g2)) ((s ś) (fs5 fs2)) (t (g5 f2)) ((u ù ú û ü) (gs5 e2)) (v (a5 eb2)) (w (bb5 d2)) (x (b5 cs2)) ((y ý ÿ) (c6 c2)) ((z ż ź) (cs6 b1)))) (text-map *map-pitch2* text) => ((g5 bb2) (b3 e4) (bb2 f5) (b2 d5 f2) (f2 d5) (b3 gs3) (f2 f3 c4 f2) (gs4 fs5) (g5 g4 gs3) (gs2 gs5 gs3 fs2 f2 gs4 bb2 cs5)) Example with a velocity map: (defparameter *map-velocity* '(((a à á â ã ä å æ ą) ppp) (b ppp) ((c ç ć) ppp) (d pp) ((e è é ê ë ę) pp) (f pp) (g p) (h p) ((i ì î ï) p) (j mp) (k mp) ((l ł) mp) (m mf) ((n ñ ń) mf) ((o ò ó ô õ ö) mf) (p f) (q f) (r f) ((s ś) ff) (t ff) ((u ù ú û ü) ff) (v fff) (w fff) (x fff) ((y ý ÿ) ffff) ((z ż ź) ffff))) (text-map *map-velocity* '(o p u s m o d u s)) => (mf f ff ff mf mf pp ff ff) Example with binary map: (defparameter *map-binary* '(((a à á â ã ä å æ ą) ((1))) (b ((1 0))) ((c ç ć) ((1 1))) (d ((1 0 0))) ((e è é ê ë ę) ((1 0 1))) (f ((1 1 0))) (g ((1 1 1))) (h ((1 0 0 0))) ((i ì î ï) ((1 0 0 1))) (j ((1 0 1 0))) (k ((1 0 1 1))) ((l ł) ((1 1 0 0))) (m ((1 1 0 1))) ((n ñ ń) ((1 1 1 0))) ((o ò ó ô õ ö) ((1 1 1 1))) (p ((1 0 0 0 0))) (q ((1 0 0 0 1))) (r ((1 0 0 1 0))) ((s ś) ((1 0 0 1 1))) (t ((1 0 1 0 0))) ((u ù ú û ü) ((1 0 1 0 1))) (v ((1 0 1 1 0))) (w ((1 0 1 1 1))) (x ((1 1 0 0 0))) ((y ý ÿ) ((1 1 0 0 1))) ((z ż ź) ((1 1 0 1 0))))) (text-map *map-binary* '(o p u s m o d u s)) => ((1 1 1 1) (1 0 0 0 0) (1 0 1 0 1) (1 0 0 1 1) (1 1 0 1) (1 1 1 1) (1 0 0) (1 0 1 0 1) (1 0 0 1 1)) Example with otherwise option. (setf map4 '((e e3) (f f3) (g fs3) (h g3) (i gs3) (j a4) (k bb3) (l b3) (m c4) (n cs4) (o d4))) (text-map map4 '(o p u s m o d u s)) => (d4 c4 d4) The result of the expression above is not equal to the length of the (o p u s m o d u s) list because the letters d, p, s and u are not in the map. Use the otherwise option to get the same count: (text-map map4 '(o p u s m o d u s) :otherwise '((eb4e5) (f3fs4))) => (d4 (eb4e5) (f3fs4) (eb4e5) c4 d4 (eb4e5) (f3fs4) (f3fs4)) In the following examples our maps are created algorithmically: (setf map (mapcar 'list (make-alphabet) (integer-to-pitch (gen-integer-step 0 26 '(1 -2 3 1))))) => ((a c4) (b cs4) (c b3) (d d4) (e eb4) (f e4) (g d4) (h f4) (i fs4) (j g4) (k f4) (l gs4) (m a4) (n bb4) (o gs4) (p b4) (q c5) (r cs5) (s b4) (t d5) (u eb5) (v e5) (w d5) (x f5) (y fs5) (z g5)) (text-map map text) => ((d5 gs4) (cs4 eb4) (gs4 cs5) (bb4 gs4 d5) (d5 gs4) (cs4 eb4) (d5 f4 c4 d5) (fs4 b4) (d5 f4 eb4) (c5 eb5 eb4 b4 d5 fs4 gs4 bb4)) (setf map2 (mapcar 'list (make-alphabet) (mapcar 'list (integer-to-pitch (gen-integer-step 0 26 '(1 -2 3 1))) (integer-to-pitch (gen-integer-step -6 26 '(1 -2 3 1)))))) => ((a (c4 fs3)) (b (cs4 g3)) (c (b3 f3)) (d (d4 gs3)) (e (eb4 a3)) (f (e4 bb3)) (g (d4 gs3)) (h (f4 b3)) (i (fs4 c4)) (j (g4 cs4)) (k (f4 b3)) (l (gs4 d4)) (m (a4 eb4)) (n (bb4 e4)) (o (gs4 d4)) (p (b4 f4)) (q (c5 fs4)) (r (cs5 g4)) (s (b4 f4)) (t (d5 gs4)) (u (eb5 a4)) (v (e5 bb4)) (w (d5 gs4)) (x (f5 b4)) (y (fs5 c5)) (z (g5 cs5))) (text-map map2 text :seed 63) => ((d5 d4) (g3 a3) (d4 cs5) (bb4 gs4 d5) (d5 d4) (g3 a3) (d5 b3 c4 d5) (c4 f4) (d5 f4 eb4) (c5 eb5 eb4 b4 d5 c4 gs4 bb4)) In the next example we map a group of letters to a group of pitches. Example: a = (c4 cs4 d4) b = (c4 cs4 d4) and c = (c4 cs4 d4) etc... (setf map3 (mapcar 'list (gen-divide 3 (make-alphabet)) (integer-to-pitch (gen-divide 3 (gen-integer 26))))) => (((a b c) (c4 cs4 d4)) ((d e f) (eb4 e4 f4)) ((g h i) (fs4 g4 gs4)) ((j k l) (a4 bb4 b4)) ((m n o) (c5 cs5 d5)) ((p q r) (eb5 e5 f5)) ((s t u) (fs5 g5 gs5)) ((v w x) (a5 bb5 b5)) ((y z) (c6 cs6 d6))) (text-map map3 text) => ((g5 c5) (cs4 f4) (c5 f5) (cs5 d5 g5) (gs5 d5) (c4 f4) (fs5 gs4 d4 g5) (g4 fs5) (gs5 g4 f4) (e5 gs5 f4 fs5 g5 gs4 c5 d5)) => ((gs5 c5) (c4 e4) (c5 eb5) (c5 c5 g5) (gs5 c5) (c4 e4) (g5 gs4 cs4 fs5) (gs4 fs5) (gs5 fs4 e4) (eb5 gs5 eb4 fs5 gs5 fs4 cs5 c5)) => . . . Best wishes to all, JP
  16. 4 points
    PatrickMimran

    SimpleSpringPianopiece

    This is a simple piano piece by Patrick Mimran . SimpleSpringPianoPiece - - Output - Stereo Out.mp3 SimpleSpringPianoPiece.opmo
  17. 4 points
    torstenanders

    alternate-omns

    Below is a function that might be interesting for others as well. When I starting writing this function it was much more complicated, but it got more simple by and by :) A formatted version as an RTF file of the documentation is attached, below is a plain text version. For completeness I also attached the documentation of the function circle-repeat, used by the function below. Unfortunately, the file names are destroyed by the software of this forum, sorry. Best, Torsten alternate-omns ids omns Arguments and Values ids a list of integers, indicating the position of OMN expressions in omns. omns a list of OMN expressions (can also be plain lengths, or pitches etc.) between which to switch. Description This function alternates between sublists of multiple OMN expressions. This function can be useful, e.g., to switch between different musical characteristics. Each characteristic (e.g., gesture) and its development can be specified by a combination of parameters (rhythm, pitches, dynamics, and playing techniques) in a sequence of OMN expressions. The output of the function switches between these characteristics as specified in the first argument to the function. The following example demonstrates this. (alternate-omns (gen-eval 10 '(rnd-pick '(0 1))) (list (make-omn :length (length-rest-series (rnd-sample 7 '(7 8 9)) (length-divide 3 2 (rnd-sample 7 '((q q q) (h e e) (h.) (h q))))) :pitch '(d4 e4 f4 g4) :velocity '(pp)) (make-omn :length '(s s s s) :pitch (gen-rotate :right '(c5 d5 f5 a5 g5 e5) :type :seq) :velocity '(ff) :span :pitch))) Alternatively, one can switch between plain sequences of OMN lengths, or pitches etc. (alternate-omns '(0 0 1 0 1 0 1 1 0 0 1 1 1) (list (gen-rotate :left '(-1/20 1/20 1/20 1/20 1/20) :type :seq) '((q e e)))) Examples Remember that resulting OMN expressions can be “re-barred”. (omn-to-time-signature (alternate-omns '(0 0 1 0 1 0 1 1 0 0 1 1 1) (list (make-omn :length (gen-rotate :left '(-1/20 1/20 1/20 1/20 1/20) :type :seq) :pitch '(d4 e4 f4 g4) :velocity '(ff)) (make-omn :length '(q e e) :pitch (gen-rotate :left '(c5 e5 f5) :type :seq) :velocity '(pp pp) :attribute '(ten stacc stacc) :span :pitch))) '(4 4)) Implementation (defun alternate-omns (ids omns) "This function alternates between sublists of multiple omn expressions. It can be useful, e.g., to switch between different musical characteristics. Args: ids: a list of integers, indicating the position of OMN expressions in omns. omns: a list of OMN expressions (can also be plain lengths, or pitches etc.) between which to switch." (let ((omn-no (length omns))) (assert (every #'(lambda (x) (and (integerp x) (< x omn-no))) ids) (ids) "alternate-omns: must be a list of integers between 0 and (1- (length omns)): ~A" ids) (let ((hash (make-hash-table))) (loop for i from 0 to (1- omn-no) for my-omn in omns ;; span (circular repeat if necessary) omn sublists to number of occurences in specs ;; and fill hash table with that as side effect do (setf (gethash i hash) (circle-repeat my-omn (count i ids)))) (alternate-omns-aux ids hash)))) (defun alternate-omns-aux (ids hash) (loop for id in ids collect (pop (gethash id hash)))) (defun circle-repeat (pattern n) "Circle through elements in pattern (a list) until n elements are collected. NOTE: only supports flat list so far." (let ((l (length pattern))) (loop for i from 0 to (- n 1) collect (nth (mod i l) pattern)))) TXT.rtf TXT.rtf
  18. 4 points
    I've started to develop a converter that converts Sibelius SoundSet files (xml) to Opusmodus SoundSet format. It's very preliminary yet but attached you'll find the result of using the Sibelius Special Edition Sound Set as well as the Sibelius Strings Sound Set as test input. Looks promising I think. The Controllers group is missing but I'll be able to implement that part soon. Need a better understanding of what it's supposed to do and will start testing the output so far. VSL has created Sibelius specific presets for Vienna Instruments which are meant to be used in conjunction with the Sibelius Sound Set. The converter I wrote converts these Sibelius Sound Set XML files into Opusmodus sound files that will work with those same Sibelius presets for Vienna Instruments. They won't work with the standard VSL presets but as far from what I understand now those Sibelius specific Sound Set formats & presets are very useful for Opusmodus too. You don't have to have Sibelius in order to use these Opusmodus sound sets. I just use the word Sibelius to make clear that the Vienna Instruments Sibelius presets shall be used. Any suggestions are more than welcome. (see post below for the latest version of the sound sets.)
  19. 4 points
    opmo

    Opusmodus 1.2.20538

    NEW: MODUS is working with omn-form lists now. (modus '((q c6 cs4 e a4 e3 d6 f4) (q b4 gs3 e bb4 eb4 g5 fs6))) => ((0 1 9 4 2 5) (11 8 10 3 7 6)) MOTIF-MAP function name has change to PATTERN-MAP with additional functionality. (setf omn '((s c4 d4 e4 f4 g4 a4 b4 c5) (5q c4 d4 e4 f4 g4 g4 f4 e4 d4 c4))) (pattern-map '(((c4 d4 e4) (cs4 ds4 f4)) ((f4 g4) (eb4 fs4))) omn :type :pitch) => ((s cs4 ds4 f4 eb4 fs4 a4 b4 c5) (5q cs4 ds4 f4 eb4 fs4 g4 f4 e4 d4 c4)) (pattern-map '(((c4 d4 e4) (cs4 ds4 f4)) ((f4 g4) (eb4 fs4))) omn :type :pitch :loop t) => ((s cs4 ds4 f4 f4 g4 a4 b4 c5) (5q c4 d4 e4 eb4 fs4 g4 f4 e4 d4 c4)) (setf mat '((q c6 cs4 a4 e3 d6 f4) (q b4 gs3 bb4 eb4 g5 fs6))) (modus mat) => ((0 1 9 4 2 5) (11 8 10 3 7 6)) (pattern-map '(((0 1 9 4 2 5) (0 4 2 1 9 5)) ((11 8 10 3 7 6) (10 8 11 3 7 6))) mat :type :pitch :pcs t) => ((q c6 e4 d4 cs3 a6 f4) (q bb4 gs3 b4 eb4 g5 fs6)) (pattern-map '(((0 1 9) (10 8 11)) ((11 8 10) (0 1 9))) mat :type :pitch :pcs t :loop t) => ((q bb6 gs4 b4 e3 d6 f4) (q c4 cs3 a4 eb4 g5 fs6))
  20. 4 points
    Stephane Boussuge

    The Planet

    Ambient soundtrack, thanks to gen-controller function for the algorithmic parameters automation ;-) SB.
  21. 4 points
    Name: Contrepoint/counterpoint Tanaeiev Category: Music Theory and Analysis Date Added: 2016-08-28 Submitter: Deb76 Bonjour, J'ai découvert dans un forum (compositeur.org) un sujet posté par un passionné de théorie musicale et du contrepoint en particulier, il mettait en exergue l'ouvrage du russe Sergueï Taneïev "Convertible Counterpoint In the Strict Style" paru en 1906 et qui aborde le contrepoint d'un point de vue mathématique. Intrigué, entre autres par sa notation numérique des intervalles (0 = unisson, 1=seconde, 2=tierce...7=octave), trouvant des similitudes d'approche avec la Set Theory et notamment les travaux de David Lewin, je me suis demandé alors que je ne maîtrise pas le contrepoint tonal si Opusmodus pouvait m'être utile dans la lecture de cet ouvrage, si je pouvais avec OPMO recréer ses exercices. D'où la recherche de fonctions qui pourraient m'aider dans cette démarche. Et de fait, j'en ai trouvé plusieurs dont INTERVALE-MAP qui permet de calculer les transpositions de ses "derivatives" mais en effectuant une conversion des intervalles, CHORD-INTERVAL-ADD, ainsi que SUBSTITUTE-MAP (suggéré par Janusz Podrazik) et qui a l'avantage de permettre l'utilisation de la notation de Taneïev. C'est une première approche de ce document mis en ligne par le site archive.org (https://archive.org/details/convertiblecount00tane), portant pour l'instant sur les outils permettant l'analyse et la lecture de cet ouvrage. Une seconde partie est prévue sur les déplacements des voix mais elle nécessite du temps, ne serait-ce que pour convertir les très nombreux exemples écrits dans les différentes clés dont les clés d'Ut 1e et 4e ligne. Le PDF de la vidéo est ici, il sera plus aisé à consulter. http://www.deb8076.eu/CAOPhotosForums/IntervalsTanaievC.pdf Hello, I found in a forum (compositeur.org) posted a subject by a passionate music theory and counterpoint in particular, he put highlight the work of Russian Sergueï Taneïev "Convertible Counterpoint In the Strict Style" published in 1906 and that addresses the counterpoint of a mathematical point of view. Intrigued, among others by its numerical notation intervals (0 = unison, 1 = second, third ... 2 = 7 = octave), finding similarities with the approach of Set Theory and including the work of David Lewin, I am asked when I do not control the tonal counterpoint if Opusmodus could help me in reading this book, if I could recreate his exercises with OPMO. Hence the search functions that could help me in this. And in fact, I found several of which INTERVAL-MAP that calculates the transpositions of its "derivatives" but with conversions intervals, CHORD-INTERVAL-ADD and SUBSTITUTE-MAP (suggested by Janusz Podrazik) and has the advantage of allowing the use of rating Taneyev. This is a first approach to the document posted by the website archive.org (https://archive.org/details/convertiblecount00tane), bringing yet on the tools for analysis and reading this book . A second part is provided on the movement of voice but it takes time, if only to convert many examples written in different keys whose key Ut 1st and 4th line. The PDF of the video is linked above, it will be easier to navigate. PS : Sorry for my bad english. Contrepoint/counterpoint Tanaeiev
  22. 4 points
    AM

    a little markov game

    ;;;little markov-game: ;;;gen-markov => analyze the output => produce new rules => gen-markov ;;;make x-times the list-plot and you will see how the system most of the times ;;;comes to a "constant STATE" (defun self-analyzing/generating-markov (transitions size generations) (loop repeat generations with list = (gen-markov-from-transitions transitions :size size :start 1) append (setq list (gen-markov-from-transitions (gen-markov-transitions list) :size size :start (car (last list)))))) ;;;a "neutral table with 4 values" (setf transition-table '((1 (1 1) (2 1) (3 1) (4 1)) (2 (1 1) (2 1) (3 1) (4 1)) (3 (1 1) (2 1) (3 1) (4 1)) (3 (1 1) (2 1) (3 1) (4 1)) (4 (1 1) (2 1) (3 1) (4 1)))) ;;;evaluate a few times and have a look on the output (list-plot (self-analyzing/generating-markov transition-table 20 20) :point-radius 0 :style :fill)
  23. 4 points
    opmo

    Coming Soon: REWRITE-LENGTHS

    (1/12 1/20 1/4 1/4 1/5 1/6) (5/32 1/32 1/4 1/32 5/32 1/4 3/32 1/32 5/32 1/16 1/16) (1/20 1/10 3/20 1/5 1/4 3/10 7/20 2/5 9/20 1/2 11/20) ((1/20 1/20 1/20) (1/10 1/20) (2/20 2/20 -1/20) (1/20 1/20) (1/12 1/2))
  24. 4 points
    Hi, Picat is a Prolog-derived language with good support for Constraint Programming. In today's blog, I have shown how to implement a simple CP-based function in Picat for chord/non-chord tone generation, and more interestingly, how we can interact with Picat from Opusmodus to get the results of the computation. To me, this opens up new possibilities for expanding what you can do from Opusmodus! Regards, Rangarajan
  25. 4 points
    ajf-

    Klangreihen Study

    Here is my study about the klangreihen: (defparameter tempo 60) (defparameter title "Klangreihen Study") ;;; This object takes care of setting and getting of parts (defclass study-score () ((instruments :initarg :instruments :initform 0) (duration :initarg :duration :initform 0) (parts))) ;;; When initializing, fill it with an empty model for parts (array of size N) (defmethod initialize-instance :after ((score study-score) &key) (let ((instruments (slot-value score 'instruments ))) (setf (slot-value score 'parts) (make-array instruments :initial-element '(-w)' :fill-pointer instruments)))) ;;; Getter and setter methods (defun get-part (score n) (elt (slot-value score 'parts) n )) (defun (setf part) (part score n) (let ((previous-value (elt (slot-value score 'parts) n))) (setf (elt (slot-value score 'parts) n) (concatenate 'list previous-value part)))) ;;; Instance of the object (defparameter study (make-instance 'study-score :instruments 16 :duration tempo)) ;;; Main procedure (let* ;; Main local variables ((12tone '(0 2 4 5 7 9 6 8 10 11 1 3)) (variants (list (row-variant 0 'r4 12tone) (row-variant 0 '4 12tone))) (total-parts (slot-value study 'instruments)) (bases (apply #'append (map 'list #'(lambda (v) (klangreihen 0 '(3 3 3 3) v)) variants))) (lengths (subseq (gen-divide total-parts (gen-length (distributive-cube (interference2 '(3 2 2))) 16)) 0 (length bases)))) (loop for base in bases for length in lengths do (labels ;; Local transformative functions ((amount-of (n) (/ 1 (nth n length))) (vel-scale (v) (+ 0.2 (* 0.6 v) )) (vel-format (v) (get-velocity (list v) :type :symbol)) (velocity-for (n) (vel-format (vel-scale (/ (amount-of n) 16)))) (length-for (n) (list (nth n length ))) (octave-of (n) (let ((low-bound (- 12 (* 12 (round (* (/ 1 total-parts) n 3.4) ))))) (list low-bound (+ low-bound 12)))) (pitch-for (n) (let* ((rolled (gen-surround base :size (amount-of n) :start n))) (ambitus (octave-of n) rolled)))) (loop for n from 0 to (- total-parts 1) do (destructuring-bind (&key length pitch velocity) ;; Example of handling on a case-by-case basis. No extra cases configured now. (case n (otherwise (list :length (length-for n) :velocity (velocity-for n) :pitch (pitch-for n) ))) (setf (part study n) (make-omn :length length :pitch pitch :velocity velocity :span :pitch))))))) ;;; Retrieve parts and save score (let ((partnum -1)) (def-score Study (:title title :composer "A. Jacomet" :key-signature 'atonal :time-signature '(4 4) :tempo tempo :layout (string-ensemble-layout '(vn11 vn12 vn13 vn14 vn21 vn22 vn23 vn24) '(vla1 vla2 vla3 vla4) '(vlc1 vlc2) '(ctb1 ctb2))) (vn11 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 1) (vn12 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 2) (vn13 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 3) (vn14 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 4) (vn21 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 5) (vn22 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 6) (vn23 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 7) (vn24 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 8) (vla1 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 9) (vla2 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 11) (vla3 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 12) (vla4 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 13) (vlc1 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 14) (vlc2 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 14) (ctb1 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 15) (ctb2 :omn (get-part study (incf partnum)) :sound 'gm :program 'Acoustic-Grand-Piano :channel 15))) (live-coding-midi (compile-score 'Study)) (display-musicxml 'Study) ;;;--------------------------------------------------------- ;;; ANNOTATION ;;;--------------------------------------------------------- #! This study is about the LISP languages and the possibilities of working with object oriented programming and loops. The first important part of this study is the 'study-score' class defined at the top of the file. (defclass study-score () ((instruments :initarg :instruments :initform 0) (duration :initarg :duration :initform 0) (parts))) On initialization, that object will create and save in one of it's properties, a model of the parts, which is an array of lists. (defmethod initialize-instance :after ((score study-score) &key) (let ((instruments (slot-value score 'instruments ))) (setf (slot-value score 'parts) (make-array instruments :initial-element '(-w)' :fill-pointer instruments)))) It is important to note that this can be extended to an N-dimensional array supporting Parts, Pitches, Velocities, Lengths, and more information. We then define trivial functions that are intended to help in adding and retrieving parts. (defun get-part (score n) (elt (slot-value score 'parts) n )) (defun (setf part) (part score n) (let ((previous-value (elt (slot-value score 'parts) n))) (setf (elt (slot-value score 'parts) n) (concatenate 'list previous-value part)))) This will eventually help keep our program free of code redundancy, and we can adapt the parts in any way we like in a global way. The rest is a simple example of utilizing a klangreihen base and looping over it. The loop starts with a LET clause that sets all the basic parameters: (let* ;; Main local variables ((12tone '(0 2 4 5 7 9 6 8 10 11 1 3)) (variants (list (row-variant 0 'r4 12tone) (row-variant 0 '4 12tone))) (total-parts (slot-value study 'instruments)) (bases (apply #'append (map 'list #'(lambda (v) (klangreihen 0 '(3 3 3 3) v)) variants))) (lengths (subseq (gen-divide total-parts (gen-length (distributive-cube (interference2 '(3 2 2))) 16)) 0 (length bases)))) ..... ) Looping over these global parameters, we start to build our theme sequentially, making all parts for each base. (loop for base in bases for length in lengths do (labels ... )) The LABELS special operator allows us to define local functions for our loop body, that will be helpful in transforming the data. Within it's function body, we have the actual loop that loops over the parts: (loop for n from 0 to (- total-parts 1) ...) The DESTRUCTURING-BIND macro allows us to keep our syntax clean and succint, because we can handle different cases using CASE, while setting Length, Velocity and Pitch, and then in a single line, retrieve those values and use them to set that particular omn in the parts array: (destructuring-bind (&key length pitch velocity) ;; Example of handling on a case-by-case basis. No extra cases configured now. (case n (otherwise (list :length (length-for n) :velocity (velocity-for n) :pitch (pitch-for n) ))) (setf (part study n) (make-omn :length length :pitch pitch :velocity velocity :span :pitch))) !#
×