Skip to content

Instantly share code, notes, and snippets.

@mauritslamers
Created June 18, 2020 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauritslamers/65b0c8f59e48ba848d71fce8750de8c3 to your computer and use it in GitHub Desktop.
Save mauritslamers/65b0c8f59e48ba848d71fce8750de8c3 to your computer and use it in GitHub Desktop.
(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