Jump to content

torstenanders

Members
  • Posts

    496
  • Joined

  • Last visited

Everything posted by torstenanders

  1. Thanks for coming back so quickly. Seemingly this does not work reliably -- the source file can be in the Navigator, but the definition is still not found. Anyway, the problem I have with the Navigator is that what it shows and the actual files and folders on the HD are not necessarily in sync. I understand that this gives users some flexibility to arrange their project, but I end up again and again manually making sure my files and the Navigator are in sync (e.g., after adding or moving files). Anyway, this has low priority :) Best, Torsten
  2. In the example below, the tongue slap is shown in the first bar in the score, but not the last. What am I missing? Thanks a lot! ((e g4 mp slap) (-e) (s e5 p stacc g5 stacc) (3h fs4 mp slap 3q slap)) Best, Torsten
  3. The Opusmodus editor (Hemlock) supports finding the source for definitions: point the cursor, e.g., on a function name and press M-. (on a Mac, the meta key is the alt key). This works nicely, e.g., for everything loaded via quicklisp, asdf and the sources of CCL itself (if the pathname is set up correctly, e.g., by adding the following to your extensions). Obviously, it cannot work for any Opusmodus definitions, because the sources are not available to us. (setf (logical-pathname-translations "ccl") '((#P"ccl:**;*.*" #P"/path/to/your/local-ccl-installation/ccl/**/*.*"))) However, looking up sources conveniently this way does *not* work for Opusmodus extensions loaded automatically from ~/Opusmodus/Extensions. Could please be fixed? This is a lower priority bug, but it would be very good to keep such reports somewhere on record. Opusmodus should have some bug reporting facilities for that. Keeping such messages somewhere in the forum makes the impression that they are easily forgotten, and therefore there is less of an incentive to report bugs :) Best, Torsten PS: Even if Opusmodus is not an open-source system, it would be good to learn from literature such as The Cathedral and the Bazaar by Eric S. Raymond (wikipedia): "Treating your users as co-developers is your least-hassle route to rapid code improvement and effective debugging."
  4. I would like to algorithmically process rhythms that contain grace notes. The function omn turns grace notes into 0 lengths, which is useful. (omn :length '((acc 1/8 1/8) 1/2 1/4)) However, I have difficulties translating them back after whatever processing of the rhythm. The function make-omn turns 0 lengths into the symbol z, but this symbol is not supported by snippet preview. (make-omn :length (omn :length '((acc 1/8 1/8) 1/2 1/4))) What am I missing here? Best, Torsten PS: Apologies for submitting so many messages.
  5. Thanks for coming back. Pretty much all Opusmodus functions calls are traced (https://en.wikipedia.org/wiki/Tracing_(software)) in the listener, when they are called. (Apologies if the link is over the top, just want to clarify.) Example, which causes a trace of rnd-pick. (loop repeat 10 collect (rnd-pick '(1 2 3))) I understand that this can be very useful for debugging, in particular if further information is shown like the function arguments etc., but I would like to disable it by default. Is that possible perhaps? BTW: Below is the definition of a very similar tracing function, that allows to control which functions are currently traced, or to switch of tracing globally. Best, Torsten (defvar *dbg-ids* NIL "Identifiers used by dbg") ;; was once named debug, but symbol debug is already defined in common-lisp (see opimize) (defun dbg (id format-string &rest args) "Print debugging info if (DEBUG ID) has been specified" (when (member id *dbg-ids*) (fresh-line *debug-io*) (apply #'format *debug-io* format-string args))) (defun start-debug (&rest ids) "Start debug output on the given ids." (setf *dbg-ids* (union ids *dbg-ids*))) (defun stop-debug (&rest ids) ; was once named undebug "Stop debug on ids. With no ids stop debugging altogether." (setf *dbg-ids* (if (null ids) NIL (set-difference *dbg-ids* ids)))) #| ; demo (defun test (x) (tu:dbg 'test "test") (list x x)) (tu::start-debug 'test) (loop repeat 10 collect (test 1)) (tu::stop-debug) |#
  6. Ah, brilliant -- thank you! Below this message is the corrected function for those interested. The following works now as expected. (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3) :seed 4321) The definition of map-neighbours is still in the other post above. > To stop the endless print in the Listener you could add DO-VERBOSE marco Thanks. I would prefer disabling such tracing globally -- I would only need it for debugging. Is that perhaps possible? Best, Torsten (defun durational-accent (lengths &key (seed nil) (divide 2) (set nil) (ignore nil)) "Adds durational accents on first notes of bars by subdividing the last note of the preceding bar. `lengths' must be a list of length lists (multiple bars). If a bar starts with a rest, then it cannot carry a durational accent, and hence its preceding note is never subdivided. Note: currently only plain length values, and no OMN supported. Args: divide (integer or list of integers, default 2): specifies into how many equal note values notes preceeding a durational accent are subdivided. If list of integer, subdivision is randomly chosen. set (length or list of lengths): only specified lengths are subdivided. ignore (length or list of lengths): specified lengths are *not* subdivided. lengths must be list of lists. For now simpler version: accents only supported leading to strong beat at beginning of bar, but metric structure does not need to be regular. Example: (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3))" (assert (and (listp lengths) (every #'listp lengths)) (lengths) "Given `lengths' ~A is not a sequence of bars (a list of lists).~%" lengths) (rnd-seed seed) (append (map-neighbours #'(lambda (bar1 bar2) (if (length-notep (first bar2)) ;; subdivide last note of bar (append (butlast bar1) (length-divide ; random control whether subdivision happens (rnd-pick '(0 1) :seed (seed)) (if (listp divide) (rnd-pick divide :seed (seed)) divide) (last bar1) :set set :ignore ignore :seed (seed))) bar1)) lengths) (last lengths)))
  7. Below is a function for creating durational accents on the beginning of bars. Many musical styles pay careful attention to how their rhythmic language expresses accents. Certain rhythmic events are perceived as stronger emphasised than others. Such accents do not need to be forced by a performer, e.g., by a dynamic accent. Instead, music theorists identified various musical factors that express accents. Durational accents (expressed by inter-onset intervals) are particularly effective. They are caused by relatively long durations following one or more shorter durations. The function definition is below. Here are two demo calls, showing multiple solutions. (durational-accent '((1/4 1/4 1/4) (1/4 1/4 -1/4) (1/4 1/4 1/4) (1/2 -1/4))) => ((1/4 1/4 1/4) (1/4 1/4 -q) (1/4 1/4 1/8 1/8) (1/2 -1/4)) => ((1/4 1/4 1/8 1/8) (1/4 1/4 -q) (1/4 1/4 1/8 1/8) (1/2 -1/4)) (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3)) => ((1/2 1/4) (1/4 1/4 1/12 1/12 1/12) (1/2 -q) (1/2 1/4) (1/4 1/4 1/12 1/12 1/12) (1/2 -1/4)) => ((1/2 1/12 1/12 1/12) (1/4 1/4 1/8 1/8) (1/2 -q) (1/2 1/8 1/8) (1/4 1/4 1/4) (1/2 -1/4)) => ((1/2 1/8 1/8) (1/4 1/4 1/4) (1/2 -q) (1/2 1/12 1/12 1/12) (1/4 1/4 1/12 1/12 1/12) (1/2 -1/4)) NB: Unfortunately, I did not get the seed argument working. I tested rnd-seed and friends with a simpler function, and everything seemed to work fine there, but I could not find what stops it working for the durational accents. Janusz: can you perhaps see what I am missing here? Best, Torsten (defun durational-accent (lengths &key (seed nil) (divide 2) (set nil) (ignore nil)) "Adds durational accents on first notes of bars by subdividing the last note of the preceding bar. `lengths' must be a list of length lists (multiple bars). If a bar starts with a rest, then it cannot carry a durational accent, and hence its preceding note is never subdivided. Note: currently only plain length values, and no OMN supported. Args: divide (integer or list of integers, default 2): specifies into how many equal note values notes preceeding a durational accent are subdivided. If list of integer, subdivision is randomly chosen. set (length or list of lengths): only specified lengths are subdivided. ignore (length or list of lengths): specified lengths are *not* subdivided. lengths must be list of lists. For now simpler version: accents only supported leading to strong beat at beginning of bar, but metric structure does not need to be regular. Example: (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3)) BUG: arg seed not working." (rnd-seed seed) (assert (and (listp lengths) (every #'listp lengths)) (lengths) "Given `lengths' ~A is not a sequence of bars (a list of lists).~%" lengths) (append (map-neighbours #'(lambda (bar1 bar2) (if (length-notep (first bar2)) ;; subdivide last note of bar (append (butlast bar1) (length-divide ; random control whether subdivision happens (rnd-pick '(0 1) :seed (seed)) (if (listp divide) (rnd-pick divide :seed (seed)) divide) (last bar1) :set set :ignore ignore)) bar1)) lengths) (last lengths))) ;; aux def (defun map-neighbours (func list &optional n) "Applying `func' to consecutive sublists of `list'. The number of arguments expected by func implicitly specifies the number of consecutive elements to which the function is applied. This can be overwritten by the optional `n'." (let ((n2 (if n n (length (ccl:arglist func))))) (loop for l on list when (>= (length l) n2) collect (apply func (subseq l 0 n2))))) #| (map-neighbours #'(lambda (x y) (list x y)) '(1 2 3 4 5 6)) => ((1 2) (2 3) (3 4) (4 5) (5 6)) (map-neighbours #'+ '(1 2 3 4 5 6) 3) => (6 9 12 15) |#
  8. Also, is it perhaps possible to globally switch off the constant tracing printout likely caused by this macro. I would prefer to only see results in the listener, and to see such tracing output only when needed for debugging. Thanks! Best, Torsten
  9. Dear Janusz and Stephane, I understand both your points, thanks for your feedback. Still, I think it would be useful if snippet output would work more like the normal evaluation, where after evaluating multiple statements/expressions only the last result is returned. Such an implicit progn is useful behaviour. Many Lisp forms therefore also have an implicit progn (e.g., the bodies of defun, lambda, and let, case, catch, when etc.). It seems that if multiple expressions are selected, then snippet output instead tries to notate/play each of them, resulting in the errors reported above. It seems a simple solution would be to enclose all code for snippet output with a progn, so that snippet output also supports an implicit progn. This would not break any existing functionality, but would fix the reported problem, which then saves time during coding (no need to evaluate multiple lines separates, or to write progn), and avoids unnecessary surprises by newcomers. Best, Torsten
  10. Just an idea for an improvement, no idea how complex this is to fix. Snippet output currently works nicely when selecting an expression that returns a supported format (e.g., OMN), like the following. (vector-to-pitch '(c4 c5) (gen-white-noise 7)) It also works when selecting and then evaluating multiple statements for snippet output, as the following example demonstrates. (setf pitches1 (vector-to-pitch '(g3 b4) (gen-white-noise 10))) (setf pitches2 (reverse pitches1)) However, other cases result in an error. For example, the following two lines (creating random results, but allowing to fix the seed later in case we like the output) work fine when evaluating and showing their result in the listener. (setf seed (random 1000)) (setf pitches1 (vector-to-pitch '(g3 b4) (gen-white-noise 10 :seed seed))) By contrast, when selecting both lines together then snippet output results in an error like. ? audition-musicxml-omn-snippet > Error: The value 976 is not of the expected type list. > While executing: parse-chord-form-from-stream, in process Listener-3(11). > Type cmd-. to abort, cmd-\ for a list of available restarts. > Type :? for other options. As the error message suggested, problematic are seemingly variables that do not bind a list. E.g., this example results in the same error as above when selecting both lines together and generating snippet output, while their normal evaluation and snippet output of only the last line just works fine. (setf no 10) (setf pitches1 (vector-to-pitch '(g3 b4) (gen-white-noise no))) ? audition-musicxml-omn-snippet > Error: The value 10 is not of the expected type list. > While executing: parse-chord-form-from-stream, in process Listener-3(11). > Type cmd-. to abort, cmd-\ for a list of available restarts. > Type :? for other options. Could that perhaps be fixed? Thanks! Best, Torsten
  11. Opusmodus already comes with a number of convenient shortcuts for auditioning and notating snippets. It would be useful to complement them by a shortcut for plotting vectors. When evaluating a vector or list of numbers, it would basically though the following code around it. (list-plot <vector or list to plot goes here> :join-points T :point-radius 2) Thanks a lot! Best, Torsten
  12. There seems to be a bug in the function gen-sine. When the argument :modulation is used (i.e. not NIL) then that seems to disable the argument :phase. The following two calls therefore have the same result. (list-plot (gen-sine 120 2 1 :phase 0 :modulation (gen-sine 120 0.5 1)) :join-points T) (list-plot (gen-sine 120 2 1 :phase 90 :modulation (gen-sine 120 0.5 1)) :join-points T) Best, Torsten
  13. > It is not that simple. I understand. Fair enough. > I agree, to add multi screen support to Opusmodus would help. That would be nice, but should perhaps not be a priority :) Anyway, I am sure many users use more than one screen. > I use Opusmodus for developing Opusmodus and have no problem with it. Perhaps you should try having multiple monitors and see after a week or so whether you ever want to move back :) For computer programmers, multiple large monitors are a standard, because it saves time = money. See, e.g., http://codingsupply.com/best-monitor-for-programming/ http://www.slothygeek.com/best-monitor-for-programming/ https://www.quora.com/What-is-the-best-type-of-computer-monitor-for-coding http://tiamat.tsotech.com/4k-is-for-programmers BTW: In contrast to what they say in these reviews, programmers beyond a certain age (e.g., me) should better choose larger monitors that specified, e.g., 32 inch for a 2560 x 1440 resolution. An turning at least one monitor into portrait mode is useful for seeing more of long code files :) Best, Torsten
  14. Yes, I saw that I can open in the Top Assistant etc. and I used that already, but then there is no room for the documentation anymore, and I still have only two source "windows" next to each other. The problem is that the workspace layout overall is fixed in the number of available "windows". To be clear, I understand that fixed arrangement of "windows" tends to be more convenient that a number of unrelated free-floating windows, but in a programming IDE you often want to have many source files and multiple views of the same file available for coding. Other programming environments therefore commonly allow to split windows an arbitrary number horizontally or vertically. Even Hemlock itself, on which AFAIK the Opusmodus IDE is based, allows to split windows: That command has seemingly been disabled in the Opusmodus IDE. Any chance to bring it back? Best, Torsten
  15. The trick for opening a file in a separate window seems simply to not have opened that file in the project already. The remaining difficulty is that a separate source window evaluates with its own listener, which is useful in some situations, but I would think the more common use case is using the same listener by all windows. Best, Torsten
  16. The Opusmodus editor allows to have a number of "windows" open next to each other, but not enough for me. With Emacs I have commonly 3-4 frames with code open next to each other, in addition to the documentation, output viewers etc. (nice to have multiple screens :) Any chance to do the same and open 3-4 files from the current project/workspace side by side? EDIT: Note that I can open additional files, but only if they are not part of the current project/workspace -- going beyond that restriction would help. Thanks! Best, Torsten
  17. OK: I changed my mind -- with a simple function like the above make-voices we can have "unnumbered" voices. Then the OMN notation can be consistent using the voice-number keywords you proposed, or whatever :) Best, Torsten
  18. Dear Janusz, After our chat last night I still think that it would be useful to make voice numbers optional. If they are absent, this could simply mean that they are in increasing order, starting with 1. So, the following two snippets would be equivalent. (:1 (q e4 ff h f4 q c5) :2 (e fs4 ff gs4 bb4 gs4 q fs4 f4) :3 (s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4)) ((q e4 ff h f4 q c5) (e fs4 ff gs4 bb4 gs4 q fs4 f4) (s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4)) Now, the problem with the latter notation is that it cannot be distinguished from a sequence of bars, which is why I proposed another notation to mark parallel voices (those brackets). Alternatively, we could simply require another level of parentheses. (((q e4 ff h f4 q c5)) ((e fs4 ff gs4 bb4 gs4 q fs4 f4)) ((s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4))) This could also be done by a simple function that expects an arbitrary number of voices with or without sublists for bars, and then creates the additional lists (or voice number markers) behind the scene. (make-voices (q e4 ff h f4 q c5) (e fs4 ff gs4 bb4 gs4 q fs4 f4) (s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4)) Anyway, as I pointed out before I suspect we quickly run into cases where the time signatures of different voices get inconsistent -- regardless of the notation used, and that it would be useful to optionally specify time signatures explicitly, like in def-score. This would simply cause a re-barring behind the scene, which is not a big deal. (make-voices (q e4 ff h f4 q c5) (e fs4 ff gs4 bb4 gs4 q fs4 f4) (s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4) :time-signature '((1 1 1 1) 4)) Tempo specifications for snippets would be very useful as well, and so would be partial scores with instrument names specified instead of voice numbers, but that might be too much :) Best, Torsten
  19. On second thought, with def-score we have exactly the same issue (which, btw is also shared by all your other voice grouping proposals above), and with def-score this is addressed by the option to specify the time signature separately. Perhaps we could do the same here? If so, perhaps we could also specify the tempo for snippets with voices? Now, I am getting greedy ;-) -- but being able to specify tempi would really be handy. E.g., [(q e4 ff h f4 q c5) (e fs4 ff gs4 bb4 gs4 q fs4 f4) (s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4) (q c3 ff h f2 q f3) :time-signature '((1 1 1 1) 4) :tempo 100] BTW: This voice group reader macro -- [...] -- would best be complemented by a pretty printing option, which ensures that any results containing such voice groups are printed with the same syntax using brackets. That way, dealing with this extended OMN data structure remains as easy and direct as OMN is so far. Behind the scenes, voice groups can then be represented with an arbitrary data structure (e.g., objects). An example for such pretty printing is shown also at http://frank.kank.net/essays/hash.html, where the hash tables are printed with the special syntax introduced there. Of course, as AM pointed out, functions for processing any such voice groups would need to use special accessor functions like omn and friends, but that is already the case with other functions processing OMN, in particular functions processing the notes of chords with their special syntax. Best, Torsten
  20. Sounds you really settle in there :) Best, Torsten
  21. Dear Janusz, I greatly welcome support for polyphony directly in OMN expressions. Thanks for plans to introduce these, and thanks for consulting us on your plans! I would prefer individual voices expressed as individual sequences, which would exclude option 1. The most easy way might be to simply express voices a lists in a list (i.e., without any necessary to name voices), but then this notation would be confused with the way OMN expresses bars in a voice (as sublists). You already introduced special syntax options for other composite data in order not to overload the notion of nested lists, by introducing your special chord symbols. So, why not introducing some special syntax for a group of voices as well like, e.g., the following. Here, a pair of brackets -- [ ... ] -- surrounds the voices, where each voice is notated with OMN as before (i.e., possibly with nested lists expressing bars, the special notation for chords etc.). [(q e4 ff h f4 q c5) (e fs4 ff gs4 bb4 gs4 q fs4 f4) (s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4) (q c3 ff h f2 q f3)] Such bracket syntax is pretty strait forward to implement in Common Lisp, likely more easy than the special OMN chord symbols, using reader macros. For an example see, e.g., https://gist.github.com/chaitanyagupta/9324402, where a much more complex syntax (JSON) is parsed with reader macros. Another example is http://frank.kank.net/essays/hash.html, which defines a custom hash-table syntax with reader macros. While I would like in principle to have an option for polyphony without the need to name individual voices (e.g., to express polyphony for keyboard instruments), it would also be very useful to optionally be able to freely name voices, e.g., according to a later def-score expression, as in the following snippet. [:flute (q e4 ff h f4 q c5) :oboe (e fs4 ff gs4 bb4 gs4 q fs4 f4) :french-horn (s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4) :bass-clarinet (q c3 ff h f2 q f3)] If the reader macro treads individual symbols as optional voice names followed by a list representing the actual voice, both notations above should be possible to support. Also, we may want to be able to express changes of the polyphony (number of parallel voices), as well as expressing sections this way. Why not using plain lists containing the proposed voice groups to expresses again sequences of musical material, as in the following example, where a two-voice section is followed by a monophonic section. ([(q e4 ff h f4 q c5) (e fs4 ff gs4 bb4 gs4 q fs4 f4)] [(s g3 ff gs3 q bb3 s gs3 g3 q gs3 f4)]) Finally, a restriction would likely be that parallel voices have to share the same metric structure. That should be easy enough to enforce by raising an exception otherwise, but it might be a case of errors users easily run into when algorithmically generating polyphonic music. So, a more smart way to deal with that would be welcome. No idea right now how to address that, though. What do you think? Best, Torsten PS: Note that I very rarely define custom reader macros, because they also have their downsides (e.g., bracket pairs would not be recognised by the Lisp editor of Opusmodus out of the box), but in this particular case I think they would be a good idea. OMN introduced its own syntax already anyway, and aims to combine readability, conciseness and simplicity. The proposed notation of groups of voices fits in that nicely in my view.
  22. > As from ver.1.2.21732 pitch, length, velocity and articulation symbols are part of the OM package and can be used with other packages. Just for completeness, does this mean all these symbols are now exported? Also, does this include user-defined articulations? BTW: For those who want to move expressions between packages, I defined the following (a very long time ago). (defun convert-to-package (form from-package to-package) "converts the given form in the given package, i.e. if package is not the current package it will add <package-name>:: in front of every symbol." (if (eq (find-package from-package) (find-package to-package)) form (cond ((null form) nil) ((listp form) (loop for item in form collect (convert-to-package item from-package to-package))) ((constantp form) form) ((symbolp form) (if (eq (symbol-package form) (find-package from-package)) (intern (symbol-name form) to-package) ; converts it to to-package form)) ; pass it unchanged otherwise (T (error "Do not know how to handle ~A" form)))))
  23. > I sometimes think I need to make my own "headings" inside of Opusmodus with my own explanation for some of the techniques and how they can be applied to my idea of composition. I simply created my own collections in files like "interesting-functions-rhythm.opmo", "interesting-functions-pitch.opmo" etc. Just added some of Stephane's suggestions -- thanks for that :) Torsten
×
×
  • Create New...

Important Information

Terms of Use Privacy Policy