Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
01-11-07 13:02 class8.scm Page 1 1 2 3 STRUCTURE AND INTERPRETATION OF MUSIC CONCEPTS 4 ______________________________________________ 5 ============================================== 6 7 CLASS 8: 8 ======== 9 Constraint Representation for Hierarchical Music-Structures or Music concepts. 10 _________________________________________________________________________ _____ 11 ========================================================================= ===== 12 13 Hierarchical concepts have to be represented by formalisms that can 14 specify grouping, possibly for any depth. 15 Such formalisms are, for example: 16 Formal grammars. 17 Natural language grammars -- like Unification grammars. 18 Expression grammars. 19 20 * The structures created by these formalisms are: 21 Trees. 22 Directed Graphs. 23 Constraint Networks. 24 25 26 * In general we get the picture: 27 Formal model ---> data structure ---rendering--> domain-element 28 as in: 29 formal grammar ---> tree ---> sentence (word) 30 natural language grammar ---> directed graph ---> sentence 31 32 33 CONSTRAINTS: A constraint on a hierarchical element usually depends on the 34 constituents of the element. In the Rhythm concept -- the constraint 35 depends on the direct constituents of the rhythm. In the Melody concept 36 -- the constraint depends on the "leaf" constituents (Melodicsegments). 37 38 REQUIREMENTS: 39 ============= 40 1. Generation. 41 2. Analysis. 42 3. Partial analysis: Combined generation/analysis. 43 4. Tuning -- an artistic requirement. 44 The material we are handling has an "evolving" character. 45 It requires the ability to be modified/refined/switched, etc. 46 That is very different from Natural languages where your task might be: 47 Analyze this sentence to see if its correct and provide the desired 48 semantics, or generate a sentence about "Bob talking to Mary in Lunch". 49 In creative tasks we need to "play" with the material. 50 51 THE CONCEPTS: 52 ============= 53 54 RHYTHM and MELODY 55 56 CLUSTER and MELODIC-SEGMENT -- not hierarchical. 01-11-07 13:02 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 class8.scm POLYPHONIC CONCEPTS e.g., ROUND. MELODY-WITH-AN-ACCOMPANIMENT (MEL-ACC). MELODY-BASED-MUSIC-STRUCTURE. ------------------------------------------------------We consider 3 options for formalizing these concepts: 1. Dircet implementation (in Scheme). 2. Grammatical rule systems. 3. Constrtaint networks. I. DIRECT IMPLEMENTATION ======================== MELODY: ~~~~~~~ Direct Music-Structures implementation: 1. Each concept is a procedural object. 2. The constituents of a omposite music structure must be part of its properties. Page 2 80 So: 81 82 A constructor for bottom-up construction (analysis): 83 (define (Melody-ms m1 m2 . rest) 84 ;;; the compatibility constraint is made part of the constructor. 85 (if (compatible (cons m1 (cons m2 rest))) 86 (begin 87 (define (process tp) 88 "sequential-adjoin of the constituent melodies" 89 (sequence->process ....) ) 90 (define (constituents) (list m1 m2 ...)) 91 "TIME-PROJECTION PROCEDURES: 92 measures <--> music time scale (points/intervals)" 93 "STRUCTURAL PROPERTIES: nesting level, length, range." 94 "PARAMETERS: rhythm, meter, melodic-line, contour." 95 ... 96 (define (me message) 97 ....) 98 me 99 ))) 100 101 102 A constructor for top-down construction (generation): 103 (define (Melody-ms) 104 (let ( (m1, m2, ... be melodies or melodic-segments such that 105 (compatible (cons m1 (cons m2 rest))) )) 106 (begin 107 (define (process tp) 108 "sequential-adjoin of the constituent melodies" 109 (sequence->process ....) ) 110 (define (constituents) (list m1 m2 ...)) 111 "TIME-PROJECTION PROCEDURES: 112 measures <--> music time scale (points/intervals)" 01-11-07 13:02 113 114 115 116 117 118 119 120 121 122 class8.scm Page "STRUCTURAL PROPERTIES: nesting level, length, range." "PARAMETERS: rhythm, meter, melodic-line, contour." ... (define (me message) ....) me ))) RHYTHM: 3 123 ~~~~~~~ 124 A constructor for bottom-up construction (analysis): 125 (define (Rhythm rhythm-tree meter ref-measure) 126 .... ) 127 128 A constructor for top-down construction (generation): 129 (define (Rhythm meter ref-measure) 130 Construct a rhythmic-tree that corresponds to the meter and reference 131 measure. 132 ....) 133 134 PROBLEMS: 135 ~~~~~~~~~ 136 1. The HIERARCHICAL STRUCTURE and its properties are burried in the 137 details of the implementation. 138 2. The CONSTRAINTS are burried in the details of the implementation. 139 3. Partial (combined) generation/analysis --> provide a constructor for 140 every option. 141 142 * We need an abstraction on the hierarchical structure 143 and the constraints. 144 * We need a flexible non-directional construction possibility. 145 146 147 II. FORMAL GRAMMAR BASED REPRESENTATION: 148 ======================================= 149 150 Hirarchical tree structures can be specified by formal (contextfree) 151 grammars. 152 The specification is obtained by RULES. For example: 153 A -> a A B 154 or 155 Sentence -> NP VP in grammar for natural languages. 156 157 A successive application of rules is a DERIVATION, which can be captured by a 158 DERIVATION TREE. 159 160 We have seen in the example taken from Norvig's book a simple way for 161 generating structured sentences (a sentence, together with its parsing) 162 that are specified by a grammar. 163 164 But the rules we have for Rhythm and for Melody do not have an explicit 165 right hand side. 166 Therefore, we cannot straightforwardly use grammatical tools that 167 REPLACE a left hand side of a rule by its right hand side. 168 We somehow need a CONSTRUCTOR for a right hand side, and a 01-11-07 13:02 class8.scm Page 4 169 PREDICATE for verifying that something is a legal right hand side. 170 As long as the constraint for a rule involves only the rule category and 171 constituents, we still can use the general 'generate' procedure of 172 Norvig for the generation of structured sentences. 173 174 TREE-RHYTHM: 175 ============ 176 The rhythm rules that were given in class 4 are: 177 178 For a meter <n m>: 179 1. <n m> --> k1/m k2/m ... kl/m where k1+k2+...+kl=n 180 181 For any music duration p= <s t>, obtained by a rule application: 182 Let q be a natural number, 183 p --> k1/q*p k2/q*p ... kl/q*p where k1+k2+...+kl=q 184 185 NOTE: The first rule is a special case of the second rule, 186 were p = <n m>, and q=n, since it can be written: 187 <n m> --> k1/n * n/m k2/n * n/m ... kl/n * n/m where k1+k2+...+kl=n 188 189 Observations and simplifications: 190 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 191 Following a discussion in class we made the suggestion that the first 192 rule is over restricting since there are rhythms were the measure is not 193 a grouping of its exact number of beats. 194 Examples: A <3 4> meter with a 2 doted 1/4-s measure. 195 A 3/4 meter with a 5-grouped measure. 196 197 ----> Therefore we suggested to omit the first rule. 198 199 A tree-rhythm is a triplet: 200 <rhythm-tree meter reference-measure> 201 explained as follows: 202 203 1. A rhythm-tree is a tree whose sub-trees are measure-trees. 204 205 2. A measure tree for a given meter is a labeled tree. 206 Nodes stand for music durations. Internal nodes stand for groups. 207 Arcs stand for the group-membership relation. 208 Leaves stand for music-durations in the rhythm. 209 * internal nodes are labeled by the group size: 210 q in the rule. 211 * Arcs are labeled by their relative share in the group: ki in 212 the rule. 213 214 3. Every node is associated with a music 215 duration -- given by the "weight" of the path leading to that node. 216 music-duration(n) = path-weight(n) * meter. 217 A path weight is defined as follows: 218 for a path ei ni-1 ... e1 n0 (e-i tree edges, n-i tree nodes, n0 -219 root, l(e) and l(n) stand for labels), leading to a node ni, 220 the weight is the 221 accumulation: l(ei) / l(ni-1) * ... * l(e1) / l(n0) 222 note that the node's label is not part of its music duration. This is 223 because the node's label is the grouping size for its child nodes, 224 and has no meaning for the node irself. 01-11-07 13:02 225 226 4. 227 228 229 230 231 5. 232 measures. 233 0. 234 235 duration 236 below). 237 238 first/last 239 class8.scm Page 5 Size: As far as the node's music duration goes, the node is a "1" sized music-duration (consider, for example, a "zoom-out" situation, where you do not want to see further details). Internal nodes have size 1. Size of leaf nodes: A rhythm-tree can be defined, uniformly, as a tree of The leaves are size-labeled (not group labeled) by either 1 or 1 -- meaning the leaf occurs (belongs) to the rhythm 0 -- meaning there is "emptyness" here -- as far as the musicgoes (Note -- this is NOT a rest -- see more about rests Restrictions: 1. 0 sized leaves can appear ONLY as prefix/suffix in the measure, respectively (to prevent "black holes" in time!). 240 2. No full measure 0 leaves. 241 242 MODIFY the music-duration of a node to be: 243 size(ni) * l(ei) / l(ni-1) * ... * l(e1) / l(n0) * meter 244 245 Advantage: under this view of measures we have a uniform 246 measure-tree, for all measures. The 0-sized leaves have 0 music 247 duration, meaning, they do not exist. 248 (suggested by Angeliena and Jung-Joo). 249 250 6. Start, reference, end, duration of a tree-rhythm: 251 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 252 Tree-rhythm: we now need to mark the reference time point, because a 253 first measure starting with 0 leaves might be either a prefix 254 (negative start) or a delay (positive start). 255 Suggestion: 256 Reference-measure is: 257 number of reference measure as a tree child (1 or 2, with the 258 restriction: if 2, then there must be 0 leaves in 1 (a prefix 259 cannot be a full measure)). 260 261 7. RESTS: 262 We need to be able to describe rests in a duration. 263 For that purpose we need a 2-valued type <Pitch/no-pitch>. 264 This should be an abstraction type for the Music-pitch type, extended 265 with a no-pitch value. 266 The leaves of the rhythm-tree are also labeled with a value in that 267 type. 268 269 8. RENDERING: 270 Compute the tree-front: A sequence of music-durations 271 (rhythmic-pattern). 272 273 Given that view of a tree-rhythm, it can be constructed using 274 a procedure, that is similar to norvig's generate-tree. Only, 275 the 'rewrite' procedure is replaced by a 'create-group' procedure. 276 277 A Different View of a rhythm-tree (suggested by Derek Leung) 278 ============================================================ 279 280 1. A GROUPING-TREE is a pair of a music-duration and a measuretree. 01-11-07 13:02 class8.scm Page 6 281 A MEASURE-TREE is defined above. 282 2. A RHYTHM-TREE for a meter <n m> is a sequence of grouping trees, such 283 that: 284 a. All sub-trees, but the first and the last are measure-trees with 285 music-duration n/m. 286 b. The first and the last sub-trees can have music durations k/l, 287 such that k/l =< n/m. 288 c. The complimantary constraint -- not mandatory: 289 If the music-duration of the first sub-tree is not n/m, then the sum 290 of the music-durations of the first and the last sub-trees is n/m. 291 292 Under this view, there is no need for complimenting a prefix or a sufix 293 measures with 0-valued leaves. 294 The definition of music-duration of a node stays the same -- only that the 295 music-duration of the group is taken instead of the overall meter. 296 297 298 PROBLEMS with using a simplistic linguistic approach: 299 1. If a constraint associated with a rule refers to indirect 300 descendents of a category -- then the direct generation is more 301 problematic -- it must be passed downword, up to the involved 302 descendents. 303 2. For music-structure concepts, like Melody: 304 They involve further dimensions, like dynamics, large-scale 305 structure, that should be considered at some point. 306 307 ----> a plain tree structure is too dull and rigid to account for these. 308 309 Indeed, in natural-language processing there are richer models, like 310 functional-unification feature grammars (FUGs), that allow for the 311 separation of the different dimensions that should be considered. 312 313 314 3. Further complication -- NETWORK STRUCTURE: 315 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 316 Consider less clear concepts, like Mel-Acc (Melody with an accompaniment). 317 Viewed as a music structure it should be defined as a simultaneous music 318 structure with 2 parts: Melody and the Accompaniment. 319 But -- it is not clear that in general, an accompaniment must have 320 life of its own. 321 For example, if we look at the Schoenberg serial music. 322 It is not clear that the clusters that are adjoined to a row make an 323 accompaniment on their own -- i.e., make a music-structure that is adjoined 324 to the row. 325 Sometimes, it seems that each of the clusters is adjoined SEPARATELY 326 at some time-point to the row. 327 It seems that rather than a melody-with-an-accompaniment we have 328 a "music-network" which is a collection of 329 adjoinments-over-time between the single melody and multiple clusters. 330 331 4. Still there is the TUNING requirement for creative tasks. 332 333 334 SUMMARY OF THE REQUIREMENTS: 335 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 336 01-11-07 13:02 class8.scm Page 7 337 1. Multiple dimensions ---> no single tree. 338 2. Need a flexible way of representation/implementation that allows for 339 partial specification (like "a melody whose second constituent is THAT 340 melodic segment, and the rest is still unknown") -- > 341 No direct implementation 342 3. Network structure for some concepts. 343 4. Hierarchy dependent constraints. 344 5. Need for TUNING. 345 346 * We do share with natural languages the: 347 * Multiple dimensions. 348 * structural combination (music-structures in music, 349 grammatical combinations in NLP) 350 * inter-refernces among the dimensions. 351 352 353 III. CONSTRAINT-NETWORK BASED REPRESENTATION FOR MUSICSTRUCTURES: 354 ================================================================== 355 356 Shift the emphasis from the structured objects to the 357 relations/operations that create the structure -- constraints. 358 Stable structure -- separate structure from concrete 359 instantiation. Network structure does not change with 360 changes in constituent values. 361 362 363 A constraint is a relation between elements. 364 For example, in the SICP example there are four relations: 365 366 Adder(a1, a2, sum) 367 Multiplier(m1, m2, product) 368 Constant(c, const) 369 Prob(c, message) 370 371 In a constraint expression like Adder(a1, a2, sum), a1, a2 and sum are 372 vaiables (connectors) that can be instantiated or not. 373 In this case -- these are real number variables. 374 375 The SICP implementation for the constraint network is imperative -376 variable (connector) instantiation is implemented via assignment (set!). 377 It is ESSENTIALLY OBJECT-ORIENTED since the variables and the relations 378 are modeled (and implemented) as objects that have a time-variant state. 379 380 Connector (variable) with object (reference) type: 381 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 382 In SICP the connectors carry number values -- primitive types. 383 There are no issues of identities of values carried by connectors: 384 Are these exactly the same (same ideantity) or just same 385 value (state). 386 But -- once the values of connectors are objects themselves 387 the issue must be determined. 388 389 There are two basic possibilities: 390 1. Connectors are identified with their object-values: Connectors 391 include their value-objects. 392 2. Connectors are separated from their values: A connector's 01-11-07 13:02 class8.scm Page 8 393 identity is distinguished from that of its values. 394 An instantiated connector can "see"/"reference"/"access" its 395 value-object, but they are two distinguished objects. 396 397 Advantages of the second approach -- separate a variable from its value: 398 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 399 1. Clear separation between sharing to replication. 400 * Replication: two connectors that happen to carry the same value 401 object. 402 * Sharing: A connector that participates in several constraints. 403 In the first approach, replication requires replication of the value404 objects: one copy per variable (connector). 405 406 Sharing and replication in general: 407 Replication: ( (lambda (x y) (+ x y)) 2 2) 408 The operator + is applied to two different objects 409 that happen to be copies of each other! 410 411 Sharing: ( (lambda (x) (+ x x)) 2) 412 The operator + is applied to a single object. 413 414 2. Music objects can be defined, independently from their 415 participation in constraints. If a constraint is imposed 416 on a music object, a connector is added. 417 The connector SEES the music object, but not vise versa. 418 Therefore, addition of constraints does not imply modification 419 for music concept definitions. 420 421 422 NETWORK EXAMPLE: 423 ________________ 424 ~~~~~~~~~~~~~~~~ 425 426 The example involves a music-note, with a possible restriction on 427 its octave-value, and with a constraint enforcing low-notes to 428 have a soft dynamics, and high notes to have a louder dynamics. 429 430 The music concepts that are involved: 431 PITCH-CLASS, OCTAVE, MUSIC-PITCH, DYNAMICS, MUSIC-NOTE. 432 433 CONSTRAINTS: 434 1. The range of the octave can be specified externally as an 435 octave-value pair. The octave music be within that range. 436 2. Low notes have a soft dynamics. 437 High notes have a louder dynamics. 438 3. Constituent constraints: impose constraints between objects 439 and their components, such that a component cannot be 440 accidentally changed. 441 442 Approach: 443 1. Define all relevant concepts. 444 2. For each object on which a constraint is imposed, define a connector, 445 that recognizes it. 446 3. Example construction: 447 * Define external connectors. 448 * Construct network. 01-11-07 13:02 class8.scm Page 9 449 * Instantiate objects in the network (objects of connectors, or 450 components of other objects). 451 452 Our NETWORK for that example involves the following objects: 453 CONNECTORS, MUSIC objects, CONSTRAINTS. 454 For visualization: connectors -- circles. 455 music concepts -- double circles. 456 constraints -- boxes. 457 lines: Participation of a connector in a constraint. 458 A music object owned by a connector. 459 460 1. CONNECTORS and MUSIC objects: 461 * A PITCH-CLASS-connector mp-pc-con and its owned PITCH-CLASS object 462 mp-pc. 463 * An OCTAVE-connector mp-octave-con and its owned OCTAVE object 464 mp-octave. 465 * A MUSIC-PITCH-connector mp-con and its owned MUSIC-PITCH object 466 mp. 467 * A DYNAMICS-connector dyn-con and its owned DYNAMICS object dyn. 468 * A MUSIC-NOTE-connector mnote-con and its owned MUSIC-NOTE 469 object mnote. 470 * An OCTAVE-RANGE-connector range-con. 471 472 2. CONSTRAINTS: 473 * Constituent constraints: 474 1. Between mp-con and mp-octave-con, 475 2. Between mp-con and mp-pc-con. 476 3. Between mnote-con and mp-con. 477 4. Between mnote-con and dyn-con. 478 * General constraints: 479 1. An octave-range-constraint between range-con and mpoctave-con. 480 2. A dynamics-octave-range-constraint between range-con and 481 dyn-con. 482 483 3. EXTERNAL CONNECTORS: mnote-con, mp-con, range-con, dyn-con. 484 The rest of the network is created internally, by a network 485 construction procedure. 486 487 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 488 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 489 ;;;;;;;;;; MUSIC CONCEPTS and CONNECTORS ;;;;;;;;;;;;;; 490 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 491 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 492 NOTE: The specification is incomplete, and not implemented! 493 ==== 494 495 PITCH-CLASS: 496 ============ 497 (define (make-pitch-class) 498 (let ((value nil)) ;value is in the range 0-11. 499 (define (get-value) value) 500 (define (set-value! new-value) 501 (set! value new-value)) 502 (define (has-value?) (not (eq? value nil))) 503 (define (names) 504 (get value pitch-class-names-table)) 01-11-07 13:02 505 506 507 508 509 510 511 512 513 class8.scm Page 10 ;; projection: (define (pitch-class->midi-in-octave-pitch) ...) ;; arithmetics: (define (pc> pc) ...) (define (pc= pc) ...) (define (pc>= pc) ...) (define (pc< pc) ...) (define (pc<= pc) ...) (define (pc- pc) ...) --> interval-class. Cyclic (modulo 12). 514 515 516 12). 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 (define (pc+ic ic) ...) --> pitch-class. Cyclic (modulo 12). (define (pc-ic ic) ...) --> pitch-class. Cyclic (modulo 12). (define (complimentary) ...) --> pitch-class. Cyclic (modulo ... ;; Process: (define (pc->mpitch) ...) (define (process) (mpitch->process (pc->mpitch)) ) (define (printable) ...) ;; A private method. (define (print) ...) (define (me request) ... ) me)) ;another constructor: (define (make-pitch-class-from-value value) (let ((pc (make-pitch-class))) (set-value! pc value))) (define default-pc (make-pitch-class-from-value 0)) Interface operations. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PITCH-CLASS-CONNECTOR: ====================== (define (make-pitch-class-connector) (let ((pc (make-pitch-class)) ;pitch-class-connector owns its pitch-class object ;-- privately. (constraints '())) (define (get-pitch-class) pc) ;Having this procedure in the interface breaks the ;privacy of pc. (define (set-value! new-value) (set-value! pc new-value) (for-each inform-about-value 'pc-value-set constraints)) (define (connect new-constraint) (if (not (memq new-constraint constraints)) (set! constraints (cons new-constraint constraints)))) (define (me request) set-value!, get-value, has-value?, get-pc, ... ) 01-11-07 13:02 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 12). 586 12). 587 (modulo 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 class8.scm Page 11 me)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INTERVAL-CLASS ============== (define (make-interval-class) (let ((value nil)) ;value is in the range 0-11. (define (get-value) value) (define (set-value! new-value) (set! value new-value)) (define (has-value?) (not (eq? value nil))) (define (names) (get value interval-class-names-table)) ;; projection: (define (interval-class->semitones) ...) ;; arithmetics: (define (ic> ic) ...) (define (ic= ic) ...) (define (ic>= ic) ...) (define (ic< ic) ...) (define (ic<= ic) ...) (define (ic-ic ic) ...) --> interval-class. Cyclic (modulo (define (ic+ic ic) ...) --> interval-class. Cyclic (modulo (define (complimentary) ...) --> interval-class. Cyclic 12). ... ;; characterization: ;; step, small, leap, dissonant, consonant. ;; Process: (define (ic->minterval) ...) (define (sim-process) (minterval->process (ic->minterval)) ) (define (seq-up-process) (minterval->process (ic->minterval)) ) (define (seq-down-process) (minterval->process (ic->minterval)) ) (define (printable) ...) ;; A private method. (define (print) ...) (define (me request) ... ) me)) 608 609 610 611 612 613 614 615 616 ;another constructor: (define (make-interval-class-from-value value) (let ((ic (make-interval-class))) (set-value! ic value))) (define default-ic (make-interval-class-from-value 0)) Interface operations. 01-11-07 13:02 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 class8.scm Page 12 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; OCTAVE ====== (define (make-octave) (let ((value nil)) ;value is in the range 0-11. (define (standard-committee-number) (- value 1)) (define (range) (cond (... bottom) (... low) (... medium) (... high) (... top))) (define (get-value) value) (define (set-value! new-value) (set! value new-value)) (define (has-value?) (not (eq? value nil))) (define (me request) ... ) me)) ;another constructor: (define (make-octave-from-value value) (let ((octave (make-octave))) (set-value! octave value))) (define default-octave (make-octave-from-value 5)) Interface operations. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 652 OCTAVE-CONNECTOR: 653 ================= 654 (define (make-octave-connector) 655 (let ((octave (make-octave)) 656 ;octave-connector owns its octave object -- privately. 657 (constraints '())) 658 (define (get-octave) octave) 659 ;This procedure in the interface breaks the privacy of octave. 660 (define (set-value! new-value) 661 (set-value! octave new-value) 662 (for-each inform-about-value 'octave-value-set constraints)) 663 (define (connect new-constraint) 664 (if (not (memq new-constraint constraints)) 665 (set! constraints 666 (cons new-constraint constraints)))) 667 (define (me request) 668 set-value!, get-value, has-value?, get-octave, ... 669 ) 670 me)) 671 672 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 01-11-07 13:02 class8.scm Page 13 673 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 674 675 MUSIC-PITCH 676 =========== 677 (define (make-mpitch) 678 (let ((octave nil) 679 (pc nil)) 680 (define (name) 681 (if (and (has-value? octave) (has-value pc)) 682 (cons (pc 'name) (octave 'value)))) 683 ;; (pc 'name) returns the main name -- first in (pc 'names). 684 ;; an mpitch name: (C . 5). 685 ;; getters and setters: 686 (define (get-octave) octave) 687 (define (get-pc) pc) 688 (define (set-octave! octave-object) 689 (set! octave octave-object)) 690 (define (set-pc! pc-object) 691 (set! pc pc-object)) 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 ;; projection: (define (mpitch->midi-pitch) ...) ;; arithmetics: (define (mp> mp) ...) (define (mc= mp) ...) (define (mp>= mp) ...) (define (mp< mp) ...) (define (mp<= mp) ...) (define (mp- mp) ...) --> music-interval. (define (mp+mi mi) ...) --> music-pitch. (define (mp-mi mi) ...) --> music-pitch. ... ;; Process: (define (mp->mnote) ...) (define (process) (mnote->process (mpc->mnote))) (define (printable) ...) ;; A private method. (define (print) ...) (define (me request) get-octave, get-pc, set-octave!, set-pc!, ... all other non-private procedures. ) me)) (define default-mpitch ((default-pc 'pc->mpitch))) ;;; other constructors: (define (make-mpitch-from-octave-pc octave pc) (let ((mpitch (make-mpitch))) (set-octave! mpitch octave) (set-pc! mpitch pc))) (define (make-mpitch-from-midi-pitch value) (let ((octave (floor (/ value 12))) (pc (remainder value 12))) (make-mpitch-from-octave-pc octave pc))) 01-11-07 13:02 729 730 731 732 733 734 735 736 class8.scm Interface operations. ;;;;;;;;;;;;;;;;;;;;;;;;;;; MUSIC-PITCH-CONNECTOR ===================== (define (make-mpitch-connector) Page 14 737 (let ((mpitch (make-mpitch)) 738 (constraints '())) 739 (define (get-mpitch) mpitch) 740 ;this is not clear -- whether we want that or we wish 741 ;to keep mpitch private to its connector. 742 ;in the latter case we might need to provide an interface 743 ;to all of the mpitch operations -- within the me interface. 744 (define (set-octave! octave-object) 745 (set-octave! mpitch octave-object) 746 (for-each inform-about-value 'octave-set constraints)) 747 (define (set-pc! pc-object) 748 (set-pc! mpitch pc-object) 749 (for-each inform-about-value 'pc-set constraints)) 750 (define (connect new-constraint) 751 (if (not (memq new-constraint constraints)) 752 (set! constraints 753 (cons new-constraint constraints)))) 754 (define (me request) 755 get-octave, get-pc, set-octave!, set-pc!, connect, 756 ... all other non-private procedures of mpitch. 757 ) 758 me)) 759 760 761 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 762 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 763 764 MUSIC-INTERVAL 765 ============== 766 (define (make-minterval) 767 (let ((octave nil) 768 (ic nil) 769 (lower-mpitch default-mpitch)) 770 (define (name) 771 (if (and (has-value? octave) (has-value ic)) 772 (cons (ic 'name) (octave 'value)))) 773 ;; getters and setters: get-octave, get-ic. 774 ;; setters: 775 (define (set-octave! octave-object) 776 (set! octave octave-object)) 777 (define (set-ic! ic-object) 778 (set! ic ic-object)) 779 780 ;; projection: 781 (define (minterval->semitones) ...) 782 ;; arithmetics: 783 (define (mi> mi) ...) 784 (define (mi= mi) ...) 01-11-07 13:02 class8.scm Page 15 785 (define (mi>= mi) ...) 786 (define (mi< mi) ...) 787 (define (mi<= mi) ...) 788 (define (mi-mi mi) ...) --> music-interval. 789 (define (mi+mi mi) ...) --> music-interval. 790 (define (complimentary) ...) --> interval-class. 791 ... 792 ;; characterization: 793 ;; step, small, leap, dissonant, consonant. 794 795 ;; Processes: 796 (define (mi->mpitch-seq) (list lower-mpitch 797 (+mpitch-minterval lower-mpitch me)) 798 ;; Using an interface arithmetic operation. 799 (define (sim-process) 800 (sequence->process (mi->mpitch-seq) 801 (lambda (mp mprocess) 802 (adjoin (mpitch->process mp) ;An interface operation. 803 zero-ti 804 mprocess)))) 805 (define (seq-up-process) 806 (mps->process (mi->mpitch-seq))) ;An interface operation. 807 (define (seq-down-process) 808 (mps->process (reverese (mi->mpitch-seq)))) 809 810 (define (printable) ...) ;; A private method. 811 (define (print) ...) 812 (define (me request) 813 ... 814 ) 815 me)) 816 (define default-minterval ((default-ic 'ic->minterval))) 817 818 ;;; another constructors: 819 (define (make-minterval-from-octave-ic octave ic) 820 (let ((minterval (make-minterval))) 821 (set-octave! minterval octave) 822 (set-ic! minterval ic))) 823 824 (define (make-minterval-from-semitones value) 825 (let ((octave (floor (/ value 12))) 826 (ic (remainder value 12))) 827 (make-minterval-from-octave-ic octave ic))) 828 829 Interface operations. 830 831 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 832 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 833 834 835 836 837 838 839 840 MUSIC-DURATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DYNAMICS ======== 01-11-07 13:02 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 octave. 875 class8.scm Page 16 (define (make-dynamics) (let ((value nil)) ;value is one of: ppp,pp,p,mf,f,ff,fff. ;; projection (define (dynamics->velocity) ;returns a range of midi-velocity values. ...) (define (get-value) value) (define (set-value! new-value) (set! value new-value)) (define (has-value?) (not (eq? value nil))) (define (me request) ... ) me)) ;another constructor: (define (make-dynamics-from-value value) (let ((dynamics (make-dynamics))) (set-value! dynamics value))) (define default-dynamics (make-dynamics-from-value 'mf)) Interface operations. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DYNAMICS-CONNECTOR: =================== (define (make-dynamics-connector) (let ((dynamics (make-dynamics)) ;dynamics-connector owns its dynamics object -- privately. (constraints '())) (define (get-dynamics) dynamics) ;this procedure in the interface breaks the privacy of (define (set-value! new-value) 876 (set-value! dynamics new-value) 877 (for-each inform-about-value 'dynamics-value-set constraints)) 878 (define (connect new-constraint) 879 (if (not (memq new-constraint constraints)) 880 (set! constraints 881 (cons new-constraint constraints)))) 882 (define (me request) 883 set-value!, get-value, has-value?, get-dynamics, ... 884 ) 885 me)) 886 887 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 888 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 889 890 MUSIC-NOTE 891 ========== 892 (define (make-mnote) 893 (let ((mpitch nil) 894 (mdur nil) 895 (dynamics nil) 896 (timbre nil)) 01-11-07 13:02 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 class8.scm Page 17 ;; getters and setters: (define (get-mpitch) mpitch) (define (get-mdur) mdur) (define (get-dynamics) dynamics) (define (get-timbre) timbre) (define (set-mpitch! mpitch-object) (set! mpitch mpitch-object)) (define (set-mdur! mdur-object) (set! mdur mdur-object)) (define (set-dynamics! dynamics-object) (set! dynamics dynamics-object)) (define (set-timbre! timbre-object) (set! timbre timbre-object)) ;; Process: (define (mnote->note ti) ...) ;see class 4. ;ti is a physical time interval -- defines the projection ;of the music-time axis on the physical-time axis. ;maybe that should be part of the mduration class. (define (mnote-ms-input ti) ...) ;see class 4. (define (process) (atomic->process (mnote-ms-input ti))) 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 (define (printable) ...) ;; A private method. (define (print) ...) (define (me request) ... ) me)) (define default-mnote ((default-mpitch 'mp->mnote))) ;;; another constructor: (define (make-mnote-from-mpitch-mdur-dynamics-timbre mpitch mdur dynamics . args) (let ((mnote (make-mnote))) (set-mpitch! mnote mpitch) (set-mdur! mnote mdur) (set-dynamics! mnote dynamics) (set-timbre! mnote (if (not (null? args)) (car args) (note-timbre default-note))))) interface operations. ;;;;;;;;;;;;;;;;;;;;;;;;;;; MUSIC-NOTE-CONNECTOR ==================== (define (make-mnote-connector) (let ((mnote (make-mnote)) (constraints '())) (define (get-mnote) mnote) (define (set-mpitch! mpitch-object) (set-mpitch! mnote mpitch-object) (for-each inform-about-value 'mpitch-set constraints)) (define (set-mdur! mdur-object) 01-11-07 13:02 953 954 955 956 957 958 959 960 961 962 class8.scm Page 18 (set-mdur! mnote mdur-object) (for-each inform-about-value 'mdur-set constraints)) (define (set-dynamics! dynamics-object) (set-dynamics! mnote dynamics-object) (for-each inform-about-value 'dynamics-set constraints)) (define (set-timbre! timbre-object) (set-timbre! mnote timbre-object) (for-each inform-about-value 'timbre-set constraints)) (define (connect new-constraint) (if (not (memq new-constraint constraints)) 963 (set! constraints 964 (cons new-constraint constraints)))) 965 (define (me request) 966 get-mpitch, get-mdur, get-dynamics, get-timbre, 967 set-mpitch!, set-mdur!, set-dynamics!, set-timbre!, connect, 968 ... all other non-private procedures of mpitch. 969 ) 970 me)) 971 972 973 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 974 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 975 ;;;;;;; CONSTRAINTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 976 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 977 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 978 979 ;; guarantees that all constraints imposed on the octave of the 980 ;; mpitch are indeed imposed on its octave object and not on another 981 ;; octave object. 982 (define (mp-octave-constraint mpitch-con octave-con) 983 (let ((mpitch ((mpitch-con 'get-mpitch))) 984 (octave ((octave-con 'get-octave)))) 985 (define (holds?) 986 "tests that octave is the octave component of mpitch" 987 (if (not (eq? (get-octave mpitch) octave)) 988 "Here we can either set the octave of mpitch into 989 octave, or produce an error (exception). 990 The problem with setting is that we can get into 991 an infinite loop -- if there is another 992 mp-octave-constraint set on mpitch") 993 (define (me request) 994 (cond ((eq? request 'octave-set) 995 holds?) 996 ;octave-set is a message produced by mpitchconnector, 997 ;upon setting the octave of its mpitch object. 998 (else 'true))) 999 (set-octave! mpitch octave) 1000 ;mpitch is directly connected to octave. 1001 (connect mpitch-con me) 1002 (connect octave-con me) 1003 me) 1004 1005 ;; guarantees that all constraints imposed on the pc of the 1006 ;; mpitch are indeed imposed on its pc object and not on another 1007 ;; pc object. 1008 (define (mp-pc-constraint mpitch-con pc-con) 01-11-07 13:02 class8.scm Page 19 1009 (let ((mpitch ((mpitch-con 'get-mpitch))) 1010 (pc ((pc-con 'get-pc)))) 1011 (define (holds?) 1012 "tests that pc is the pc component of mpitch" 1013 (if (not (eq? (get-pc mpitch) pc)) 1014 "Here we can either set the pc of mpitch into pc, or 1015 produce an error (exception). 1016 The problem with setting is that we can get into 1017 an infinite loop -- if there is another 1018 mp-pc-constraint set on mpitch") 1019 (define (me request) 1020 (cond ((eq? request 'pc-set) 1021 holds?) 1022 ;pc-set is a message produced by mpitch-connector, 1023 ;upon setting the pc of its mpitch object. 1024 (else 'true))) 1025 (set-pc! mpitch pc) 1026 ;mpitch is directly connected to pc. 1027 (connect mpitch-con me) 1028 (connect pc-con me) 1029 me) 1030 1031 ;; guarantees that all constraints imposed on the mpitch of the 1032 ;; mnote are indeed imposed on its mpitch object and not on another 1033 ;; mpitch object. 1034 (define (mnote-mp-constraint mnote-con mpitch-con) 1035 (let ((mnote ((mnote-con 'get-mnote))) 1036 (mpitch ((mpitch-con 'get-mpitch)))) 1037 (define (holds?) 1038 "tests that mpitch is the mpitch component of mnote" 1039 (if (not (eq? (get-mpitch mnote) mpitch)) 1040 "Here we can either set the mpitch of mnote into mpitch, 1041 or produce an error (exception). 1042 The problem with setting is that we can get into 1043 an infinite loop -- if there is another 1044 mnote-mp-constraint set on mnote") 1045 (define (me request) 1046 (cond ((eq? request 'mpitch-set) 1047 holds?) 1048 ;mpitch-set is a message produced by mnoteconnector, 1049 ;upon setting the mpitch of its mnote object. 1050 (else 'true))) 1051 1052 1053 1054 1055 1056 1057 1058 another 1059 1060 1061 1062 1063 1064 (set-mpitch! mnote mpitch) ;mnote is directly connected to mpitch. (connect mnote-con me) (connect mpitch-con me) me) ;; guarantees that all constraints imposed on the dynamics of the ;; mnote are indeed imposed on its dynamics object and not on ;; dynamics object. (define (mnote-dyn-constraint mnote-con dyn-con) (let ((mnote ((mnote-con 'get-mnote))) (dynamics ((dyn-con 'get-dynamics)))) (define (holds?) "tests that dynamics is the dynamics component of mnote" 01-11-07 13:02 class8.scm Page 20 1065 (if (not (eq? (get-dynamics mnote) dynamics)) 1066 "Here we can either set the dynamics of mnote into 1067 dynamics, or produce an error (exception). 1068 The problem with setting is that we can get into 1069 an infinite loop -- if there is another 1070 mnote-dyn-constraint set on mnote") 1071 (define (me request) 1072 (cond ((eq? request 'dynamics-set) 1073 holds?) 1074 ;dynamics-set is a message produced by mnoteconnector, 1075 ;upon setting the dynamics of its mnote object. 1076 (else 'true))) 1077 (set-dynamics! mnote dynamics) 1078 ;mnote is directly connected to dynamics. 1079 (connect mnote-con me) 1080 (connect dyn-con me) 1081 me) 1082 1083 1084 1085 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1086 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1087 1088 RANGE-CONNECTOR 1089 =============== 1090 (define (make-range) 1091 (let ((low-value 0) 1092 (high-value 128) 1093 (constraints '())) 1094 (define (get-low-value) low-value) 1095 (define (get-high-value) high-value) 1096 (define (low-characterization) 1097 "finds the octave-range, e.g., bottom" ) 1098 (define (high-characterization) 1099 "finds the octave-range, e.g., top" ) 1100 (define (get-high-value) high-value) 1101 (define (set-low-value! new-value) 1102 (set! low-value new-value) 1103 (for-each inform-about-value 'range-low-value-set constraints)) 1104 (define (set-high-value! new-value) 1105 (set! high-value new-value) 1106 (for-each inform-about-value 'range-low-value-set constraints)) 1107 (define (connect new-constraint) 1108 (if (not (memq new-constraint constraints)) 1109 (set! constraints 1110 (cons new-constraint constraints)))) 1111 (define (me request) 1112 ... 1113 ) 1114 me)) 1115 1116 ;; OCTAVE-RANGE-CONSTRAINT 1117 ;; guarantees that octave value is within the range. 1118 ;; If not -- the octave-value is set. 1119 (define (octave-range-constraint octave-con range-con) 1120 (define (holds?) 01-11-07 13:02 class8.scm Page 21 1121 "tests that octave mpitch-values are within the 1122 range number-interval" 1123 (and (has-value? octave-con) 1124 (<= ((range-con 'low-value)) ((octave-con 'get-value))) 1125 (>= ((range-con 'high-value)) ((octave-con 'getvalue))))) 1126 (define (process-new-octave-value) 1127 ;following either range change, or octave value change. 1128 (if (not (holds?)) 1129 (let ((value ("select an octave value within the range."))) 1130 ((octave-con 'set-value) value)))) 1131 (define (me request) 1132 (cond ((or (eq? request 'range-set) 1133 (eq? request 'octave-value-set)) 1134 process-new-octave-value) 1135 ;setting the range might imply also setting 1136 ;the octave value. 1137 ;setting the octave value implies checking 1138 ;whether it is within the range restriction. 1139 ;If not --> new setting for the octave value. 1140 (else 'true))) 1141 (connect octave-con me) 1142 (connect range-con me) 1143 me) 1144 1145 1146 ;; DYNAMICS-OCTAVE-RANGE-CONSTRAINT 1147 ;; Constrains the dynamics such that: 1148 ;; 1. If the low-characterization of the octave-range connector 1149 ;; is above low, then the dynamics should be at least mf. 1150 ;; 2. If the high-characterization of the octave-range connector 1151 ;; is below high, then the dynamics should be at most mf. 1152 ;; Low notes ahould be played softer, high notes should be 1153 ;; played louder. 1154 ;; Range value dominates dynamics! 1155 (define (dynamics-octave-range-constraint dynamics-con range-con) 1156 (define (holds?) 1157 "tests that dynamics and range values satisfy the 1158 above restrictions." 1159 (and (has-value? dynamics-con) 1160 (or (and (memq ((range-con 'low-characterization)) 1161 '(high top)) 1162 (memq ((dynamics-con 'get-value)) '(mf f ff fff)))) 1163 (or (and (memq ((range-con 'high-characterization)) 1164 '(bottom low)) 1165 (memq ((dynamics-con 'get-value)) '(ppp pp p mf)))))) 1166 (define (process-new-dynamics-value) 1167 ;following either range change, or dynamics value change. 1168 (if (not (holds?)) 1169 (let ((value ("select a dynamics value that 1170 satisfies the constraint."))) 1171 ((dynamics-con 'set-value) value)))) 1172 (define (me request) 1173 (cond ((or (eq? request 'range-set) 1174 (eq? request 'dynamics-value-set)) 1175 process-new-dynamics-value) 1176 ;setting the range might imply also setting the 01-11-07 13:02 class8.scm Page 22 1177 ;dynamics value. 1178 ;setting the dynamics value implies checking whether the 1179 ;constraint holds. 1180 ;If not --> new setting for the dynamics value. 1181 (else 'true))) 1182 (connect dynamics-con me) 1183 (connect range-con me) 1184 me) 1185 1186 1187 ; Apply the dynamics-octave-range-constraint to the octave-range 1188 ; and dynamics connectors of a music note. 1189 (define (mnote-dynamics-octave-range-constraint mnote-con rangecon) 1190 (let ((dynamics-con 1191 "retrives from mnote-con its dynamics-con -1192 related to it via the mnote-dyn-constraint, if 1193 any. This requires further machinery for 1194 recognizing the type of a constraint")) 1195 (dynamics-octave-range-constraint dynamics-con range-con))) 1196 1197 1198 1199 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1200 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1201 ;;;;;;;;; NETWORK CONSTRUCTION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1202 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1203 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1204 1205 ;;; A durationless network for music note, with the above octaverange 1206 ;;; and dynamics restrictions. 1207 (define (mnote-nodur-network 1208 mnote-con mp-con range-con dynamics-con) 1209 (let ((octave-con (make-octave-connector)) 1210 (pc-con (make-pitch-class-connector))) 1211 (mp-pc-constraint mp-con pc-con) 1212 (mp-octave-constraint mp-con octave-con) 1213 (mnote-mp-constraint mnote-con mp-con) 1214 (mnote-dyn-constraint mnote-con dynamics-con) 1215 (octave-range-constraint octave-con range-con) 1216 (dynamics-octave-range-constraint dynamics-con range-con))) 1217 1218 1219 (define (set-value! connector new-value . message) 1220 (if (null message) 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 ((connector 'set-value!) new-value) ((connector (car message)) new-value))) (define mmote-con (make-mnote-connector)) (define mp-con (make-mpitch-connector)) (define range-mp-con (make-range-connector)) (define dynamics-mp-con (make-dynamics-connector)) (mp-network mnote-con mp-con range-mp-con dynamics-mp-con) (set-value! mp-con (make-pitch-class-from-value 0) 'set-pc!) (set-value! range-mp-con (cons 6 7)) (get-value mp-con 'octave) --> an octave 6 or 7. 01-11-07 13:02 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 class8.scm Page (set-value! dynamics-mp1-con 'pp) ---> the dynamics-octave-range-constraint should change the dynamics value to one of mf, f, ff, fff.! Structure-oriented order of construction: 1. Create external connectors. 2. Create network. 3. Fill in objects. 23