Adding viewpoints » History » Version 11
Version 10 (Marcus Pearce, 2013-07-23 01:49 PM) → Version 11/18 (Marcus Pearce, 2013-07-23 01:53 PM)
h1. Adding Viewpoints
h2. Basic viewpoints
# Add the viewpoint definition to <code>basic-viewpoints.lisp</code> in the directory <code>viewpoints</code>:
<pre>
;; Note ornaments (0 = no ornament; 1 = accacciatura; 2 = mordent; 3 =
;; trill
(define-basic-viewpoint ornament (events)
(md:ornament (last-element events)))
</pre>
# Add a column to the mtp-event table in the database
<pre>(clsql:execute-command <pre>
(clsql:execute-command "ALTER TABLE mtp_event ADD ornament INT DEFAULT 'NULL';")</pre> '0';")
</pre>
# In <code>events/events.lisp</code>:
add the slot definition <code>(ornament :initarg :ornament :accessor ornament)</code> to the class definition for <code>music-event</code>
# In <code>events/music-db.lisp</code>:
add <code>[ornament]</code> to the obvious places in the variable <code>*event-attributes*</code>.
# Export the new viewpoint from the <code>music-data</code> package: do this in <code>events/package.lisp</code> adding <code>"ornament"</code> to the list of exported symbols from the package <code>music-data</code>.
# If you want the basic viewpoint to be instantiated in data imported from :lisp or :mid formats, then add the following line to <code>database/music-data.lisp</code> to the list of slot instantiations in the method <code>insert-event</code>:
<pre>:ornament (cadr (assoc :ornament event))</pre>
h2. Derived viewpoints
The procedure for adding derived viewpoints is to add the viewpoint definition to one of the files in <code>viewpoints/derived-viewpoints/</code> using the macro <code>define-viewpoint</code> which has the following signature:
<pre>(define-viewpoint (viewpoint-name viewpoint-type (type-set)) (events element) :function viewpoint-function :function* inverse-function)</pre>
* _viewpoint-name_: a symbol naming the viewpoint
* _viewpoint-type_: a symbol giving the type of the derived viewpoint (<code>derived</code> for primitive derived; <code>test</code> for test; <code>threaded</code> for threaded)
* _type-set_: a list of basic viewpoints that this viewpoint is derived from and, therefore, capable of predicting
* _events_: a symbol denoting the first argument to ''viewpoint-function'' and ''inverse-function''
* _element_: a symbol denoting the second argument to ''inverse-function''
* _viewpoint-function_: a function of arity 1, which accepts a list of events, the <code>events</code> symbol above, representing a melody and returns a value from the domain of the viewpoint being defined or the <code>+undefined+</code> symbol
* _inverse-function_: a function of arity 2, accepting a list of events and an element from the domain of the viewpoint, which returns the element from the domain of the basic viewpoint which would generate the supplied element if applied to the supplied event list with the last element removed (implemented for purposes of efficiency only and not required).
h3. Example
Define a viewpoint <code>cpint</code> returning the pitch interval in semitones between the final two notes in a melodic sequence given a basic viewpoint <code>cpitch</code> which encodes chromatic pitch in semitones as midi note numbers:
<pre>
(define-viewpoint (cpint derived (cpitch))
(events element)
:function (multiple-value-bind (e1 e2)
(values-list (last events 2))
(if (or (null e1) (null e2)) +undefined+
(let ((cpitch1 (cpitch (list e1)))
(cpitch2 (cpitch (list e2))))
(if (undefined-p cpitch1 cpitch2) +undefined+
(- cpitch2 cpitch1)))))
:function* (list (+ element (cpitch (list (penultimate-element events))))))
</pre>
h2. Basic viewpoints
# Add the viewpoint definition to <code>basic-viewpoints.lisp</code> in the directory <code>viewpoints</code>:
<pre>
;; Note ornaments (0 = no ornament; 1 = accacciatura; 2 = mordent; 3 =
;; trill
(define-basic-viewpoint ornament (events)
(md:ornament (last-element events)))
</pre>
# Add a column to the mtp-event table in the database
<pre>(clsql:execute-command <pre>
(clsql:execute-command "ALTER TABLE mtp_event ADD ornament INT DEFAULT 'NULL';")</pre> '0';")
</pre>
# In <code>events/events.lisp</code>:
add the slot definition <code>(ornament :initarg :ornament :accessor ornament)</code> to the class definition for <code>music-event</code>
# In <code>events/music-db.lisp</code>:
add <code>[ornament]</code> to the obvious places in the variable <code>*event-attributes*</code>.
# Export the new viewpoint from the <code>music-data</code> package: do this in <code>events/package.lisp</code> adding <code>"ornament"</code> to the list of exported symbols from the package <code>music-data</code>.
# If you want the basic viewpoint to be instantiated in data imported from :lisp or :mid formats, then add the following line to <code>database/music-data.lisp</code> to the list of slot instantiations in the method <code>insert-event</code>:
<pre>:ornament (cadr (assoc :ornament event))</pre>
h2. Derived viewpoints
The procedure for adding derived viewpoints is to add the viewpoint definition to one of the files in <code>viewpoints/derived-viewpoints/</code> using the macro <code>define-viewpoint</code> which has the following signature:
<pre>(define-viewpoint (viewpoint-name viewpoint-type (type-set)) (events element) :function viewpoint-function :function* inverse-function)</pre>
* _viewpoint-name_: a symbol naming the viewpoint
* _viewpoint-type_: a symbol giving the type of the derived viewpoint (<code>derived</code> for primitive derived; <code>test</code> for test; <code>threaded</code> for threaded)
* _type-set_: a list of basic viewpoints that this viewpoint is derived from and, therefore, capable of predicting
* _events_: a symbol denoting the first argument to ''viewpoint-function'' and ''inverse-function''
* _element_: a symbol denoting the second argument to ''inverse-function''
* _viewpoint-function_: a function of arity 1, which accepts a list of events, the <code>events</code> symbol above, representing a melody and returns a value from the domain of the viewpoint being defined or the <code>+undefined+</code> symbol
* _inverse-function_: a function of arity 2, accepting a list of events and an element from the domain of the viewpoint, which returns the element from the domain of the basic viewpoint which would generate the supplied element if applied to the supplied event list with the last element removed (implemented for purposes of efficiency only and not required).
h3. Example
Define a viewpoint <code>cpint</code> returning the pitch interval in semitones between the final two notes in a melodic sequence given a basic viewpoint <code>cpitch</code> which encodes chromatic pitch in semitones as midi note numbers:
<pre>
(define-viewpoint (cpint derived (cpitch))
(events element)
:function (multiple-value-bind (e1 e2)
(values-list (last events 2))
(if (or (null e1) (null e2)) +undefined+
(let ((cpitch1 (cpitch (list e1)))
(cpitch2 (cpitch (list e2))))
(if (undefined-p cpitch1 cpitch2) +undefined+
(- cpitch2 cpitch1)))))
:function* (list (+ element (cpitch (list (penultimate-element events))))))
</pre>