Yann
test
f23825d
raw
history blame
3.07 kB
import { Measure } from "../measure/Measure"
export interface Beat {
measure: number
beat: number
tick: number
}
export type BeatWithX = Beat & {
x: number
}
// 範囲内の measure を探す。最初の要素は startTick 以前のものも含む
// Find Measure within the range.The first element also includes something before StartTick
const getMeasuresInRange = (
measures: Measure[],
startTick: number,
endTick: number,
) => {
let i = 0
const result: Measure[] = []
for (const measure of measures) {
const nextMeasure = measures[i + 1]
i++
// 最初の measure を探す
// Find the first MEASURE
if (result.length === 0) {
if (nextMeasure !== undefined && nextMeasure.startTick <= startTick) {
continue // 次の measure が最初になりうる場合はスキップ
// Skip if the next Measure can be the first
}
if (measure.startTick > startTick) {
console.warn("There is no initial time signature. Use 4/4 by default")
result.push({ startTick: 0, measure: 0, numerator: 4, denominator: 4 })
} else {
result.push(measure)
}
}
// 残りの measure を探す. 最初の measure がない場合に正しく処理できるように else ではなくもう一度最初の measure があるか調べる
// Find the remaining MEASURE. If you can handle correctly if you do not have the first MEASURE, check if you do the first MEASURE, rather than ELSE
if (result.length !== 0) {
if (measure.startTick <= endTick) {
result.push(measure)
} else {
break
}
}
}
return result
}
export const createBeatsInRange = (
allMeasures: Measure[],
timebase: number,
startTick: number,
endTick: number,
): Beat[] => {
const beats: Beat[] = []
const measures = getMeasuresInRange(allMeasures, startTick, endTick)
measures.forEach((measure, i) => {
const nextMeasure = measures[i + 1]
const ticksPerBeat = (timebase * 4) / measure.denominator
// 次の小節か曲の endTick まで拍を作る
// Make a beat up to the next bar or song EndTick
const lastTick = nextMeasure ? nextMeasure.startTick : endTick
const startBeat = Math.max(
0,
Math.floor((startTick - measure.startTick) / ticksPerBeat),
)
const endBeat = (lastTick - measure.startTick) / ticksPerBeat
for (let beat = startBeat; beat < endBeat; beat++) {
const tick = measure.startTick + ticksPerBeat * beat
beats.push({
measure: measure.measure + Math.floor(beat / measure.numerator),
beat: beat % measure.numerator,
tick,
})
}
})
return beats
}
export const createBeatsWithXInRange = (
allMeasures: Measure[],
pixelsPerTick: number,
timebase: number,
startTick: number,
width: number,
): BeatWithX[] => {
const endTick = startTick + width / pixelsPerTick
return createBeatsInRange(allMeasures, timebase, startTick, endTick).map(
(b) => ({
...b,
x: Math.round(b.tick * pixelsPerTick),
}),
)
}