Jump to content
Sign in to follow this  
  • entries
  • comments
  • views

Patterns replacement

Stephane Boussuge


Patterns finding and replacement can be very useful when composing.

For example, we may want to replace some unwanted motive in a melody, or we may want to generate articulation or velocity based on some patterns of length or pitch.

Another use is to compose a new section based on and old one with patterns replacement from old to new etc, etc... the possibility are naturally endless.


I propose here a function named motive-replace who are able to execute this task.

This function is not in a "good" Lisp but works for me and i hope it can be useful for other users.

Naturally, if you can improve this function, i invite you to share your thoughts on this blog.

First, we define some utility function, starting with a function for find one motive and replace it:

(defun one-motive-replace (old new mat)
     for idx from 0 to (-(length mat)1)
     collect (if (equal 
                    for i from 0 to (-(length old)1)
                     collect (nth (+ idx i) mat))
               (and (setf idx (+ idx (-(length old)1)))
               (nth idx mat)))))

(one-motive-replace  '(a b c) '(1 2 3)  '(d b s a b c e j g))
=> (d b s 1 2 3 e j g)
(one-motive-replace  '(a b c) '(1 2) '(d b s a b c e j g))
=> (d b s 1 2 e j g)


Now, we define a function able to find and replace multiple motives:

(defparameter *res* '())
(defun multi-motives-replace (oldlist newlist mat)
  (cond ((null oldlist) '())
        (t (setf *res* (one-motive-replace (car oldlist) (car newlist) mat))
           (multi-motives-replace (cdr oldlist) (cdr newlist) *res*)))

(multi-motives-replace '((a b c) (e j)) '((1 2 3) (8 9))  '(d b s a b c e j g))
=> (d b s 1 2 3 8 9 g)


And finally we define the final function for motivic-replacement who choose between one or multiple motif replace functions based on the list predicate of the first parameter:

(defun motive-replace (old new mat)
  "motive-replace will find an exact motive (old) in a list
  and will replace it by a new one (new).
  Note: It is not pattern matching but can be useful."
  (if (listp (car new))
    (multi-motives-replace old new mat)
    (one-motive-replace old new mat))))
(motive-replace '(a b c) '(1 2 3)  '(d b s a b c e j g))
=> (d b s 1 2 3 e j g)
(motive-replace '(a b c) '(1 2) '(d b s a b c e j g))
=> (d b s 1 2 e j g)
(motive-replace '((a b c) (e j)) '((1 2 3) (8 9)) '(d b s a b c e j g))
=> (d b s 1 2 3 8 9 g)



Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now