totalDuration property
Real duração que a quiáltera ocupa no compasso, em semibreves.
Soma a duração escrita de cada elemento e aplica a razão
normalNotes / actualNotes uma única vez.
A implementação anterior lia apenas a PRIMEIRA nota e multiplicava por actualNotes, o que assumia que toda quiáltera é homogênea. Isso estava errado em três casos comuns:
- duraçōes mistas — uma tercina de colcheia + semínima + colcheia é perfeitamente legal e era medida como três colcheias;
- quiálteras só com pausas ou só com acordes —
whereType<Note>()não encontrava nada e a duração virava 0.0, colapsando o tempo de tudo que vinha depois; - quiálteras aninhadas — o grupo interno não era contado.
Como o onset musical de cada evento é derivado daqui, um erro deste valor desloca tudo o que segue — inclusive o alinhamento entre pautas e a seleção por intervalo de tempo.
Apojaturas não contam. Uma nota de ornamento (Note.isGraceNote) é
um ornamento, não parte do valor escrito do grupo: ela é desenhada e
ocupa largura, mas o relógio não avança por ela. Essa é exatamente a
regra que Measure.musicalValueOf (e o MidiMapper) já aplicam, e as
duas implementações discordavam: medido, uma tercina 3:2 contendo uma
apojatura devolvia totalDuration = 0.3333 contra
musicalValueOf = 0.25. Como o LayoutEngine usa musicalValueOf para
o onset e o resto do pacote lê totalDuration, a grade de onsets
compartilhada do ADR-002 — a única razão pela qual duas pautas de um
grande sistema se alinham — divergia para qualquer quiáltera ornamentada.
Implementation
double get totalDuration {
if (elements.isEmpty) return 0.0;
double written = 0.0;
for (final element in elements) {
if (element is Note) {
if (element.isGraceNote) continue;
written += element.duration.realValue;
} else if (element is Rest) {
written += element.duration.realValue;
} else if (element is Chord) {
// Um acorde soa uma vez, não uma vez por nota.
written += element.duration.realValue;
} else if (element is Tuplet) {
// Já traz a própria razão aplicada.
written += element.totalDuration;
}
}
return written * ratio.modifier;
}