-
-
Save mauritslamers/65b0c8f59e48ba848d71fce8750de8c3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(define (interpret-staff staff-number) | |
"interprets the event list of a specific staff number" | |
(let* ( | |
(events (get-events-for-staff staff-number)) | |
(isChanged #f) | |
(previousEvent '()) | |
(previousNoteEvent '()) | |
(currentKeySig #f) | |
(currentTimeSig #f) | |
(insideSlur #f) | |
(slurOverlap #f) | |
(insideMelisma #f) | |
(sort-list! events sort-list-by-time) | |
(melismaEvents '()) | |
(slurEvents '()) | |
(forceOctavePrefix #f) | |
) | |
;; we provide every object with enough information that it should be able to | |
;; generate itself. This loop is intended to change properties where necessary | |
;; | |
(for-each | |
(lambda (evt) | |
(case (assoc-ref evt 'type) | |
( (keychange) | |
(define prevValue (assoc-ref evt 'brailleSpaceBefore)) | |
;; check whether a space is required before the key sig. | |
;; if it is the first, no, if it is the first on a line (ie previousEvent has 'breakAfter) | |
;; otherwise yes | |
(if (not currentKeySig) | |
(assoc-set! evt 'brailleSpaceBefore #f) ;;first key sig, no space before | |
(if (assoc-ref previousEvent 'breakAfter) ;;else | |
(assoc-set! evt 'brailleSpaceBefore #f) ;;set to false if breakAfter | |
(assoc-set! evt 'brailleSpaceBefore #t) ;; set to true otherwise | |
) | |
) | |
(if (not (equal? prevValue (assoc-ref evt 'brailleSpaceBefore))) | |
(set! isChanged #t) | |
) | |
(set! forceOctavePrefix #t) | |
) | |
( (time-signature) | |
;; a time signature has the more or less the same rules as the key signature, | |
;; with the exception that if it is after a key change, it doesn't need a | |
;; space before | |
(define prevValue (assoc-ref evt 'brailleSpaceBefore)) | |
(if (not currentTimeSig) | |
(assoc-set! evt 'brailleSpaceBefore #f) ;; no space | |
(if (assoc-ref previousEvent 'breakAfter) ;; else | |
(assoc-set! evt 'brailleSpaceBefore #f) ;;set to false if breakAfter | |
(if (equal? (assoc-ref previousEvent 'type) 'keychange) ;; else if the previous event is a key change | |
(assoc-set! evt 'brailleSpaceBefore #f) ;;set to false if after key change | |
(assoc-set! evt 'brailleSpaceBefore #t) ;; set to true otherwise | |
) | |
) | |
) | |
(if (not (equal? prevValue (assoc-ref evt 'brailleSpaceBefore))) | |
(set! isChanged #t) | |
) | |
) | |
( (slur-start) | |
;; for slurs we cannot simply rely on the slurMelismaBusy property, as there | |
;; can be an overlap: a note receiving both an end and a start. | |
;; Lilypond sends the events in order of code, which would make things complex here | |
;; Therefore registerBrailleEvent will check and revert the order so we | |
;; will receive an overlap always with the second start first. | |
(if insideSlur | |
(begin | |
(set! slurOverlap #t) ;; overlap | |
(set! insideSlur #t) ;; | |
) | |
(begin | |
(set! insideSlur #t) ;; no overlap, but insideSlur | |
(set! slurOverlap #f) | |
) | |
) | |
) | |
( (slur-end) | |
;; we only end the insideSlur when we are not in overlap, otherwise the | |
;; note doesn't realize something happened | |
(if (not slurOverlap) | |
(set! insideSlur #f) | |
) | |
) | |
( (phrasing-slur-start) | |
) | |
( (phrasing-slur-end) | |
) | |
( (note) | |
;; first set the previous note event, so a note can know what to do | |
(assoc-set! evt 'previousNoteEvent previousNoteEvent) | |
;; what we also need to do is to indicate whether a slur or melisma is going on | |
;; and what kind it is. | |
;; it is also interesting to see whether we can do this in reverse, and whether it | |
;; makes more sense to do it that way... | |
;; it does in a way, as we can also fix anything that might be wrong later | |
;; what needs to be done: | |
;; - check whether melismaBusy or slurMelismaBusy triggers (goes from #f to #t) | |
;; - start collecting (backwards) | |
;; - check whether melismaBusy or slurMelismaBusy triggers (goes from #t to #f) | |
;; - start walking the collection backward and set slurBefore and slurType | |
(if (assoc-ref evt 'melismaBusy) | |
(begin | |
(if (not insideMelisma) | |
(set! insideMelisma #t) | |
) | |
(set! melismaEvents (cons event melismaEvents));; add to melismaEvents | |
) | |
(begin ;; else | |
(if insideMelisma | |
(begin | |
(apply-slur melismaEvents #f) ;; a melisma is a slur event in braille, no overlap | |
(set! melismaEvents '()) | |
(set! insideMelisma #f) | |
) | |
) | |
) | |
) | |
;; then there is the slurs and phrasing slurs | |
;; and with them the overlaps. | |
;; two situations: | |
;; - insideSlur is on, meaning that we can gather slur-events | |
;; - insideSlur is on AND slurOverlap is on: this means we need to | |
;; process the gathered slur-notes, and also indicate that | |
;; that we don't have to show a slurEnd | |
(if (and insideSlur slurOverlap) | |
(begin | |
(apply-slur slurEvents slurOverlap) | |
(set! slurEvents '()) | |
(set! slurOverlap #f) | |
) | |
(if insideSlur ;; else | |
(set! slurEvents (cons event slurEvents)) | |
;; not insideSlur, check whether slurEvents still has something | |
(if (not (empty? slurEvents)) | |
(begin | |
(apply-slur slurEvents slurOverlap) | |
(set! slurEvents '()) | |
) | |
) | |
) | |
) | |
;; now the same for phrasingSlur | |
;; essentially the same for slur | |
;; implement a bit later | |
;; other important things: the first note after a time signature | |
;; needs an octave mark | |
(if (forceOctaveMark) | |
(begin | |
(set! forceOctavePrefix #f) | |
(assoc-set! evt 'forceOctavePrefix true) | |
) | |
) | |
(set! previousNoteEvent evt) | |
) | |
( (rest) | |
;; no need to do anything for rests | |
) | |
( (tie) | |
;; no need to do anything for ties | |
) | |
( (cadenza-change) | |
;; something with cadenza on, which it sets but nothing happens... | |
;; issue is that cadenza as is doesn't get a nice example in crolick, so I have | |
;; no idea how this should be notated... | |
) | |
( (break) | |
;; by itself nothing happens at a break | |
) | |
( (lyric) | |
;; can be collected? | |
) | |
( (bar-line) | |
) | |
) | |
;; set the previous values | |
(set! previousEvent evt) | |
) | |
events | |
) | |
isChanged ;; we return whether a change has taken place, might be possible to do otherwise | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment