Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #lang racket
- ;Base class for music elements
- (define (music-element)
- (let ((typeof (lambda () 'music-element)))
- (lambda (message)
- (cond ((eq? message 'typeof) typeof)
- (else (error "Member" message " not found"))))))
- ;Pauses for duretion of length. Useful in sequences.
- (define (pause length)
- (if (and (number? length) (< 0 length))
- (let ((super (music-element))
- (getlength (lambda () length))
- (typeof (lambda () 'pause))
- (scale (lambda (factor) (pause (* length factor)))))
- (lambda (message)
- (cond ((eq? message 'getlength) getlength)
- ((eq? message 'typeof) typeof)
- ((eq? message 'scale) scale)
- ((eq? message 'transpose) (pause length))
- (else (super message)))))
- (error "Malformed pause")))
- (define (pause? obj)
- (eq? (send 'typeof obj) 'pause))
- ;Note is the building block of the melody
- (define (note length pitch instrument)
- (if (and (number-in-interval 0 127 pitch) (number-in-interval 0 8 instrument))
- (letrec ((super (pause length))
- (buildfromsuper (lambda (newpause) (note (send 'getlength newpause) pitch instrument)))
- (getpitch (lambda () pitch))
- (getinstrument (lambda () instrument))
- (typeof (lambda () 'note))
- (scale (lambda (factor) (buildfromsuper (send 'scale super factor))))
- (transpose (lambda (addition) (note length (+ addition pitch) instrument))))
- (lambda (message)
- (cond ((eq? message 'getpitch) getpitch)
- ((eq? message 'getinstrument) getinstrument)
- ((eq? message 'typeof) typeof)
- ((eq? message 'scale) scale)
- ((eq? message 'transpose) transpose)
- (else (super message)))))
- (error "Malformed note")))
- (define (note? obj)
- (eq? (send 'typeof obj) 'note))
- ;A sequence of music elements played one after the other. For most basic use, a sequence of notes and pauses.
- (define (music-sequence elementlist)
- (if (and (list? elementlist)
- (andmap (lambda (element) (or (pause? element) (note? element) (music-sequence? element) (music-parallel? element))) elementlist))
- (letrec ((super (music-element))
- (getelementlist (lambda () elementlist))
- (typeof (lambda () 'music-sequence))
- (getlength (lambda ()
- (apply + (map (create-caller 'getlength) elementlist))))
- (scale (lambda (factor)
- (music-sequence (map (create-caller 'scale factor) elementlist))))
- (transpose (lambda (addition) (music-sequence (map (create-caller 'transpose addition) elementlist)))))
- (lambda (message)
- (cond ((eq? message 'getlength) getlength)
- ((eq? message 'typeof) typeof)
- ((eq? message 'scale) scale)
- ((eq? message 'getelementlist) getelementlist)
- ((eq? message 'transpose) transpose)
- (else (super message)))))
- (error "Malformed sequence")))
- (define (music-sequence? obj)
- (eq? (send 'typeof obj) 'music-sequence))
- ;A set of music elements that start playing at the same time
- (define (music-parallel elementlist)
- (letrec ((super (music-sequence elementlist))
- (buildfromsuper (lambda (newsequence) (music-parallel (send 'getelementlist newsequence))))
- (getlength (lambda () (apply max (map (create-caller 'getlength) elementlist))))
- (scale (lambda (factor) (buildfromsuper (send 'scale super factor))))
- (transpose (lambda (factor) (buildfromsuper (send 'scale super factor))))
- (typeof (lambda () 'music-parallel)))
- (lambda (message)
- (cond ((eq? message 'getlength) getlength)
- ((eq? message 'typeof) typeof)
- ((eq? message 'scale) scale)
- ((eq? message 'transpose) transpose)
- (else (super message))))))
- (define (music-parallel? obj)
- (eq? (send 'typeof obj) 'parallel))
- ;Helper for calling members
- (define (send message obj . par)
- (let ((method (obj message)))
- (apply method par)))
- ;Returns a function that given an object will call the given member of that object
- (define (create-caller class-member . args)
- (lambda (object)
- (apply (object class-member) args)))
- ;Checks if a number is within interval (including min and max)
- (define (number-in-interval min max number)
- (if (andmap number? (list min max number))
- (and (>= number min) (<= number max))
- (error "Parameter is not a number")))
- ;Tries to transpose an
- ;test
- (define testpause (pause 5))
- (define testnote (note 7 5 3))
- (define testnote2 (note 1 6 4))
- (define testsequence (music-sequence (list testnote2 testnote testnote testnote2)))
- (define testparallel (music-parallel (list testpause testnote testnote testpause)))
- (map (create-caller 'getpitch) (send 'getelementlist (send 'transpose testsequence 4)))
- (map (create-caller 'getpitch) (send 'getelementlist testsequence))
- (send 'typeof (send 'scale testparallel 1))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement