/usr/share/denemo/actions/denemo-modules/rhythmandmeter.scm is in denemo-data 2.0.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | (use-modules (ice-9 optargs)) ; optional (define* ) arguments
#!(define-module (actions denemo-modules rhythmandmeter)
#:export (
GetPrevailingTimeSig
GetMeasureTicks
EmptyMeasure?
UnderfullMeasure?
FullDurationMeasure?
OverfullMeasure?
MeasureComplete?
duration::GuessBaseNoteInTicks
duration::CalculateTicksWithDots
duration::CalculateDotsFromTicks
duration::CalculateDotsFromTicks
duration::GetNumberOfDotsInDenemo
duration::denemo->lilypond
duration::lilypond->denemo
duration::denemo->ticks
duration::lilypond->ticks
duration::ticks->denemo
duration::ticks->lilypond
duration::SplitTicksToBaseDurations
duration::GetNumberOfDotsInTicks
duration::GetNumberOfDotsInTicks
duration::GetNumberOfDotsInTicks
duration::ChangeNoteDurationInTicks
duration::InsertBaseDurationList
duration::GetNumerator
duration::GetDenominator
duration::GetDenominatorInTicks
duration::GetWholeMeasureInTicks
duration::GetMetricalPosition
duration::MetricalMain?
;d-GetStartTick
)) !#
(define* (GetPrevailingTimeSig #:optional (numberorstring #f) )
(if numberorstring
(string->number (d-InsertTimeSig "query=timesigname"))
(d-InsertTimeSig "query=timesigname")))
;(define (d-GetStartTick)
; (- (d-GetEndTick) (d-GetDurationInTicks)))
;Get Measure Filling Status in Ticks
(define (GetMeasureTicks)
(let script ((return 0))
(d-PushPosition)
(GoToMeasureEnd)
(set! return (d-GetEndTick))
(d-PopPosition)
return))
;;;the tick count at the end of the object at the cursor
(define (GetTickCount)
(let ((tick (d-GetEndTick)))
(if tick
tick
0)))
(define (MeasureFillStatus)
(define MaxTicks (* 1536 (GetPrevailingTimeSig #t) )) ; How many ticks are in a 100% filled measure?
(define ActualTicks (GetMeasureTicks))
(cond
((not ActualTicks) #f) ; empty
((< ActualTicks MaxTicks) #f) ; underful
((= MaxTicks ActualTicks) 1) ; 100% filled
((< MaxTicks ActualTicks) 2) ; >100% filled
(else (display "strange!")))) ; ?
(define (EmptyMeasure?)
(not (d-GetEndTick)))
(define (ZeroDurationMeasure?)
(or (EmptyMeasure?) (= (d-GetEndTick) 0)))
(define (UnderfullMeasure?)
(or (EmptyMeasure?)
(not (MeasureFillStatus))))
(define (FullDurationMeasure?)
(and (not (UnderfullMeasure?))
(= 1 (MeasureFillStatus))))
(define (OverfullMeasure?)
(eq? 2 (MeasureFillStatus)))
;;(and (not (EmptyMeasure?))
;; (> (d-GetEndTick) (* 1536 (GetPrevailingTimeSig #t)))))
(define (MeasureComplete?)
(d-RefreshCache)
(FullDurationMeasure?))
;;;;;;;;;;Duration Conversions between Denemo, Lilypond and Tick syntax.
;; A table of common values
; 6 = 256 = 8
;12 = 128 = 7
;24 = 64 = 6
;48 = 32 = 5
;96 = 16 = 4
;192 = 8 = 3
;384 =4 = 2
;768 = 2 = 1
;1536 = 1 = 0
;3072 = 0.5 = -1 ; Breve. 0.5 and -1 are not existend. Lilypond and Denemo use the string breve instead.
; Guile returns a value with .0, which should be exact but internally it's inexact. So we need this little back and forth conversion hack.
(define (duration::inexact->exact return)
(inexact->exact (string->number (number->string return))))
;Some functions, like Upbeat, know only a single tick-value. They need to guess the baseNote.
(define (duration::GuessBaseNoteInTicks ticks)
; first guess the basic note duration. 2*x > ticks < 1*x is always true in our circumstance
(cond
( (and (>= ticks 6) (< ticks 12)) 6 ) ;1/256
( (and (>= ticks 12) (< ticks 24)) 12 ) ;1/128
( (and (>= ticks 24) (< ticks 48)) 24) ;1/64
( (and (>= ticks 48) (< ticks 96)) 48 ) ;1/32
( (and (>= ticks 96) (< ticks 192)) 96) ;sixteen 1/16
( (and (>= ticks 192) (< ticks 384)) 192 ) ; eight 1/8
( (and (>= ticks 384) (< ticks 768)) 384 ) ; quarter 1/4
( (and (>= ticks 768) (< ticks 1536)) 768) ; half 1/2
( (and (>= ticks 1536) (< ticks 3072)) 1536 ) ; whole 1
( (and (>= ticks 3072) (< ticks 6144)) 3072 ) ; breve 2*1
( (and (>= ticks 6144) (< ticks 12288)) 6144) ; longa 4*1
( (and (>= ticks 12288) (< ticks 24576)) 12288 ) ; maxima 8*1
(else #f)))
; Calculate a new Duration in Ticks with a basic note value and a number of augmentation-dots
(define (duration::CalculateTicksWithDots baseTicks numberOfDots)
; x = basic note value
; n = number of dots
; 2x - x/2^n
(- (* 2 baseTicks) (/ baseTicks (expt 2 numberOfDots))))
; Calculate how many dots a tick value has. Needs base duration, too.
(define (duration::CalculateDotsFromTicks ticks base)
; x = base , y = ticks. result is the number of dots
; log(x/(2*x-y)) / log(2)
(define return (/ (log (/ base (- (* base 2) ticks))) (log 2) ))
(duration::inexact->exact return))
; Get Number of Dots from a Lilypond string like "2.". Its so basic it will work on Denemo notes, too.
(define (duration::GetNumberOfDotsInLilypond input)
(length (cdr (string-split input #\.))))
; For the sake of completenes. Denemo and Lilypond dot-syntax is just the same, only the number itself is different.
(define (duration::GetNumberOfDotsInDenemo input)
(duration::GetNumberOfDotsInLilypond input))
(define (duration::denemo->lilypond number)
(define return (expt 2 number))
return)
(define (duration::lilypond->denemo number)
(define return (/ (log number) (log 2)) )
(duration::inexact->exact return))
(define (duration::denemo->ticks number) ; increases with negative integers
(define return (* (expt 2 (- 8 number)) 6))
return)
(define (duration::lilypond->ticks number) ; increases with 0.5, 0.25 etc.
(define return (* (expt 2 (- 8 (/ (log number) (log 2)))) 6))
(duration::inexact->exact return))
; Ticks->Denemo wants a number but returns a string because of dots
(define* (duration::ticks->denemo number #:optional (basenumber number))
(define numberOfDots (duration::CalculateDotsFromTicks number basenumber))
;n = -(log(y/3)-9*log(2))/log(2)
(define return (- (/ (- (log (/ basenumber 3)) (* 9 (log 2))) (log 2))))
(set! return (duration::inexact->exact return))
(string-append (number->string return) (string-concatenate (make-list numberOfDots "."))))
;Ticks->Lilypond wants a number but returns a string because of dots
(define* (duration::ticks->lilypond number #:optional (basenumber number))
;Equation in readable form: http://www.numberempire.com/equationsolver.php?function=y+%3D+6*2^%288-n%29&var=n&answers=
(define numberOfDots (duration::CalculateDotsFromTicks number basenumber))
(define return (expt 2 (- (/ (- (log (/ basenumber 3)) (* 9 (log 2))) (log 2)))))
(set! return (duration::inexact->exact return))
(string-append (number->string return) (string-concatenate (make-list numberOfDots "."))))
;SplitTicksToBaseDurations wants a single tick value as number and splits it to the lowest count of base durations
;;Returns a list of base durations
;;TODO: if the last step is no BaseDuration return it anyway and an additional #f to signal the problem. Most likely someone tried to involve an incomplete tuplet.
;;TODO: Basic version. Duration will be correct but maybe ugly.
(define (duration::SplitTicksToBaseDurations ticks)
(let loop ((number ticks) (returnlist (list #f)))
(define basedur (duration::GuessBaseNoteInTicks number))
(if basedur
(loop (- number basedur) (append returnlist (list basedur)))
(if (= number 0)
(list-tail returnlist 1)
(list-tail (append returnlist (list number #f)) 1)))))
;;;;;;;;;; End of duration-conversion
;; Applied duration scripts
(define (duration::GetNumberOfDotsInTicks) ; Fails for tuplets
(duration::CalculateDotsFromTicks (d-GetDurationInTicks) (duration::GetBaseDurationInTicks)))
(define (duration::GetBaseDurationInTicks)
(define ticks (d-GetBaseDurationInTicks))
(if ticks
(abs ticks)
#f))
(define (duration::GetSelectionDurationInTicks)
(if (d-MarkStatus)
(apply + (MapToSelection d-GetDurationInTicks Music?))
#f))
(define* (duration::ChangeNoteDurationInTicks ticks #:optional (dots 0))
; First change the base-duration. The d-Change commands also delete any dots.
(define (changeBase number) (case number
;((12288) (d-ChangeMaxima)) ;Maxima
((6144) (d-ChangeLonga)) ; Longa
((3072) (d-ChangeBreve)) ; Breve
((1536) (d-Change0)) ; Whole
((768) (d-Change1)) ; Half
((384) (d-Change2)) ; Quarter
((192) (d-Change3)) ; Eighth
((96) (d-Change4)) ; Sixteenth
((48) (d-Change5)) ; 1/32
((24) (d-Change6)) ; 1/64
((12) (d-Change7)) ; 1/128
((6) (d-Change8)) ; 1/256
(else #f )))
; Second step: add dots
; d-ChangeN work on appending position, but Breve and Longa not. But d-AddDot works on appending, too. So we must rule Appending out, else it will add dots without changing the duration for breve and longa.
(if (and (Music?) (integer? ticks) (integer? dots) (changeBase ticks)) ; <-- the action changeBase itself needs to be a test, too.
(let loop ((i 0))
(if (= dots i)
#t
(begin
(d-AddDot)
(loop (+ i 1)))))
#f))
(define (duration::InsertBaseDurationList basedurlist ansNotes)
(define itemnumber (length basedurlist))
(let loop ((counter 0))
(if (and (> counter 0) (= (list-ref basedurlist counter) (/ (list-ref basedurlist (1- counter)) 2))) ; current duration is half of previous one = current is a dot. First position excluded.
(begin (d-MoveCursorLeft) (d-AddDot) (d-MoveCursorRight))
(begin (ANS::InsertNotes ansNotes) (d-MoveCursorLeft) (duration::ChangeNoteDurationInTicks (list-ref basedurlist counter)) (d-ToggleTie) (d-MoveCursorRight)))
(if (>= counter (1- itemnumber))
(begin (d-MoveCursorLeft) (d-ToggleTie) (d-MoveCursorRight) #t) ; last item was already inserted. Undo the last tie. The End.
(begin (loop (1+ counter))))))
;; Meter related functions
(define (duration::GetNumerator) (string->number (car (string-split (GetPrevailingTimeSig) #\/))))
(define (duration::GetDenominator) (string->number (cadr (string-split (GetPrevailingTimeSig) #\/))))
(define (duration::GetDenominatorInTicks) (* 1536 (/ 1 (duration::GetDenominator))))
(define (duration::GetWholeMeasureInTicks) (* 1536 (GetPrevailingTimeSig #t)))
(define (duration::GetMetricalPosition)
(if (MeasureEmpty?)
1
(1+ (/ (d-GetStartTick) (duration::GetDenominatorInTicks)))))
(define (duration::MetricalMain? position) (integer? position))
|