Adding viewpoints » History » Version 16

Marcus Pearce, 2014-11-03 05:23 PM

1 1 Marcus Pearce
h1. Adding Viewpoints
2 1 Marcus Pearce
3 1 Marcus Pearce
h2. Basic viewpoints
4 1 Marcus Pearce
5 15 Marcus Pearce
This shows the process of adding a basic viewpoint, using the <code>ornament</code> viewpoint as an example.
6 15 Marcus Pearce
7 14 Marcus Pearce
# Add the viewpoint definition to <code>basic-viewpoints.lisp</code> in the directory <code>viewpoints</code>. Here as an example for the ornament basic viewpoint:
8 4 Marcus Pearce
<pre>
9 14 Marcus Pearce
;; Note ornaments (0 = no ornament; 1 = accacciatura; 2 = mordent; 3 = trill)
10 1 Marcus Pearce
(define-basic-viewpoint ornament (events)
11 4 Marcus Pearce
  (md:ornament (last-element events)))
12 5 Marcus Pearce
</pre>
13 1 Marcus Pearce
# Add a column to the mtp-event table in the database (NB: SQL doesn't like hyphens so best avoid them)
14 1 Marcus Pearce
<pre>(clsql:execute-command "ALTER TABLE mtp_event ADD ornament INT DEFAULT '0';")</pre>
15 16 Marcus Pearce
# In <code>music-objects/music-objects.lisp</code>: 
16 14 Marcus Pearce
add <code>[ornament]</code> to the obvious place in the variable <code>*event-attributes*</code>.
17 16 Marcus Pearce
# In <code>music-objects/music-object.lisp</code>: 
18 14 Marcus Pearce
add the slot definition <code>(ornament :initarg :ornament :accessor ornament)</code> to the class definition for <code>music-event</code>.
19 16 Marcus Pearce
# In <code>music-objects/package.lisp</code>:
20 14 Marcus Pearce
Export the new viewpoint from the <code>music-data</code> package by adding <code>"ORNAMENT"</code> to the list of exported symbols from the package <code>music-data</code>.
21 14 Marcus Pearce
# in <code>database/music-data.lisp</code>:
22 14 Marcus Pearce
If you want the basic viewpoint to be instantiated in data imported from :lisp or :mid formats, then add the following line to the list of slot instantiations in the method <code>insert-event</code>:
23 10 Marcus Pearce
<pre>:ornament       (cadr (assoc :ornament event))</pre>
24 14 Marcus Pearce
note that this will only work if you add code to the relevant import module in <code>database/data-import/</code>.
25 1 Marcus Pearce
26 1 Marcus Pearce
h2. Derived viewpoints
27 1 Marcus Pearce
28 9 Marcus Pearce
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:
29 1 Marcus Pearce
30 2 Marcus Pearce
<pre>(define-viewpoint (viewpoint-name viewpoint-type (type-set)) (events element) :function viewpoint-function :function* inverse-function)</pre>
31 1 Marcus Pearce
32 1 Marcus Pearce
* _viewpoint-name_: a symbol naming the viewpoint 
33 1 Marcus Pearce
* _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)
34 1 Marcus Pearce
* _type-set_: a list of basic viewpoints that this viewpoint is derived from and, therefore, capable of predicting
35 1 Marcus Pearce
* _events_: a symbol denoting the first argument to ''viewpoint-function'' and ''inverse-function''
36 1 Marcus Pearce
* _element_: a symbol denoting the second argument to ''inverse-function''
37 1 Marcus Pearce
* _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
38 1 Marcus Pearce
* _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).
39 1 Marcus Pearce
40 1 Marcus Pearce
h3. Example
41 1 Marcus Pearce
42 1 Marcus Pearce
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:
43 1 Marcus Pearce
44 1 Marcus Pearce
<pre>
45 1 Marcus Pearce
(define-viewpoint (cpint derived (cpitch))
46 1 Marcus Pearce
    (events element) 
47 1 Marcus Pearce
  :function (multiple-value-bind (e1 e2)
48 1 Marcus Pearce
                (values-list (last events 2))
49 1 Marcus Pearce
              (if (or (null e1) (null e2)) +undefined+
50 1 Marcus Pearce
                  (let ((cpitch1 (cpitch (list e1)))
51 1 Marcus Pearce
                        (cpitch2 (cpitch (list e2))))
52 1 Marcus Pearce
                    (if (undefined-p cpitch1 cpitch2) +undefined+
53 1 Marcus Pearce
                        (- cpitch2 cpitch1)))))
54 1 Marcus Pearce
  :function* (list (+ element (cpitch (list (penultimate-element events))))))
55 1 Marcus Pearce
</pre>