Git Product home page Git Product logo

Comments (3)

defaultxr avatar defaultxr commented on May 27, 2024 1

Ok, I added prest in commit b4fba7e. It turns out adding it was easier than I was thinking it'd have to be. It should work as intended now but let me know if you come across any issues with it.

from cl-patterns.

defaultxr avatar defaultxr commented on May 27, 2024

I haven't gotten to look into it since the last time I tried implementing prest but I think the clock changes I made in the process of implementing play-quant/end-quant should make it easier to implement prest "the right way" (or at least, the way that feels right to me). Still probably need to do some restructuring of the way multichannel expansion works, though. In the meantime, I think something like this could work as a stopgap solution to embed rests in arbitrary pattern slots:

(pb :test
  :instrument :default
  :degree (pseq '((0 2) (1 3) (:rest 4) (3 :rest) 0 :rest 2 :rest) 1)
  :embed (pf (let* ((key :degree)
                    (val (e key)))
               (typecase val
                 (symbol (event :type :rest key 1))
                 (number (event :type :note))
                 (list (event :type (mapcar (lambda (i) (if (symbolp i) :rest :note)) val)
                              key (mapcar (lambda (i) (if (symbolp i) 1 i)) val))))))
  :dur 1)

The :embed pattern parses the :degree and changes the event to a rest type if it detects a symbol. This should be usable for most keys, you just have to put it after the key you want to embed rests in, and then change the (key :degree) so it refers to the name of the key in question. There are definitely some caveats to doing this, though (like how you can't do (prest 3) to specify the numeric value the rest is replaced with) and it might not work for everything. But once prest is actually implemented there shouldn't be as many of those sorts of caveats (ideally none).

from cl-patterns.

defaultxr avatar defaultxr commented on May 27, 2024

Oh, I missed the second line of your post when I read it initially, somehow. If you want to try adding it yourself, you're certainly welcome to give it a look! The way I attempted to add it before was by changing the raw-set-event-value function defined in event.lisp. This is what I tried changing it to:

(defun raw-set-event-value (event key value)
  "Set the value of KEY to VALUE in EVENT without running any conversion functions."
  (with-slots (event-plist) event
    (flet ((handle-prest (item)
             (if (typep item 'prest)
                 (progn
                   (setf event-plist (plist-set event-plist :type :rest))
                   (slot-value item 'value))
                 item)))
      (let ((value (if (listp value)
                       (mapcar #'handle-prest value)
                       (handle-prest value))))
        (setf event-plist (plist-set event-plist (make-keyword key) value))))))

I defined the prest class in patterns.lisp underneath

(defmethod as-pstream ((item pbind-pstream))
  item)

like so:

;;; prest

(defclass prest ()
  ((value :initarg :value :initform 1)))

(defun prest (&optional (value 1))
  "Make a prest object, which, when used in a `pbind' or similar event pattern, turns the current event into a rest and yields VALUE for the key's value.

Note that this is not a pattern; it is just a regular function that returns an object.

Example:

;; (next-upto-n (pbind :degree (pseq (list 0 1 (prest 2) 3) 1)))
;; ;=> ((EVENT :DEGREE 0) (EVENT :DEGREE 1) (EVENT :TYPE :REST :DEGREE 2) (EVENT :DEGREE 3))

See also: `pbind', `pbind''s :type key"
  (make-instance 'prest :value value))

(defmethod rest-p ((prest prest))
  t)

But there is definitely more restructuring that would be needed than just those two things. In particular the multichannel expansion; it will likely need to be moved either into pbind's next method or better yet an :around next method for pattern or the like (so it applies to all patterns automatically without needing to be manually implemented for each, ideally)... At least, I think. Right now it's done in the clock-process method with the code (split-event-by-lists (event-with-raw-timing event task)).

The code should be able to pass these tests if prest is implemented properly:

(test prest
  "Test `prest'"
  (is (equal (list nil t nil)
             (mapcar #'rest-p (next-upto-n
                               (pbind :dur (pseq (list 1 (prest 2) 1) 1)
                                      :dur (p+ (pk :dur) 1)))))
      "prest does not work properly as a :dur value")
  (is (equal (list 2 3 2)
             (mapcar #'dur (next-upto-n
                            (pbind :dur (pseq (list 1 (prest 2) 1) 1)
                                   :dur (p+ (pk :dur) 1)))))
      "prest's value is not used as the value of the key it is used in")
  (is (equal (list nil t nil)
             (mapcar #'rest-p (next (pbind :freq (list 1 (prest 2) 1)
                                           :freq (p+ (pk :freq) 1)))))
      "prest does not work properly with multichannel expansion")
  (is-true (rest-p (prest))
           "`rest-p' is not true for prest"))

Good luck if you do decide to give it a try, and let me know if you have any questions. :) Otherwise I will probably get time to implement it soon.

from cl-patterns.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.