|
@@ -12,6 +12,7 @@ import {
|
|
|
GRADIENT_SPEED_RESET_TAG,
|
|
|
StringUtil,
|
|
|
} from '/osmd-extended/src'
|
|
|
+import dayjs from 'dayjs'
|
|
|
const browserInfo = browser()
|
|
|
|
|
|
const getLinkId = (): string => {
|
|
@@ -145,6 +146,17 @@ export const createSpeedInfo = (gradualChange: GradualChange | undefined, speed:
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
+const tranTime = (str: string = '') => {
|
|
|
+ let result = str
|
|
|
+ const splits = str.split(':')
|
|
|
+ if (splits.length === 1) {
|
|
|
+ result = `00:${splits[0]}:00`
|
|
|
+ } else if (splits.length === 2) {
|
|
|
+ result = `00:${splits[0]}:${splits[1]}`
|
|
|
+ }
|
|
|
+ // console.log(`1970-01-01 00:${result}0`)
|
|
|
+ return `1970-01-01 00:${result}0`
|
|
|
+}
|
|
|
export const getAllNodes = (osmd: any) => {
|
|
|
const detailId = getLinkId()
|
|
|
let fixtime = browserInfo.huawei ? 0.08 : 0 //getFixTime()
|
|
@@ -175,6 +187,9 @@ export const getAllNodes = (osmd: any) => {
|
|
|
}
|
|
|
return realKey
|
|
|
}
|
|
|
+ if (state.gradualTimes) {
|
|
|
+ console.log('合奏速度', state.gradual, state.gradualTimes)
|
|
|
+ }
|
|
|
if (osmd?.cursor) {
|
|
|
try {
|
|
|
osmd.cursor.reset()
|
|
@@ -189,6 +204,7 @@ export const getAllNodes = (osmd: any) => {
|
|
|
/** 弱起时间 */
|
|
|
let difftime = 0
|
|
|
let beatUnit = 'quarter'
|
|
|
+ let useGradualTime = 0
|
|
|
let gradualSpeed
|
|
|
let gradualChange: GradualChange | undefined
|
|
|
let gradualChangeIndex = 0
|
|
@@ -212,8 +228,6 @@ export const getAllNodes = (osmd: any) => {
|
|
|
cursorBox.y = cursorImg.offsetTop
|
|
|
cursorBox.w = cursorImg.offsetWidth
|
|
|
cursorBox.h = cursorImg.offsetHeight
|
|
|
- // console.log(cursorImg.offsetLeft, cursorImg.offsetTop, cursorImg.offsetWidth, cursorImg.offsetHeight)
|
|
|
- // console.log(cursorImg.getAttribute('style'))
|
|
|
}
|
|
|
const voiceEntries = iterator.currentVoiceEntries?.[0] ? [iterator.currentVoiceEntries?.[0]] : []
|
|
|
const voiceEntries2 = iterator.currentVoiceEntries?.[1]
|
|
@@ -266,8 +280,20 @@ export const getAllNodes = (osmd: any) => {
|
|
|
let { wholeValue, numerator, denominator, realValue: noteRealValue } = note.length
|
|
|
|
|
|
let relativeTime = usetime //realValue * 4 * (60 / measureSpeed)
|
|
|
- // 速度不能为0
|
|
|
- // 此处的速度应该是按照设置的速度而不是校准后的速度,否则mp3速度不对
|
|
|
+ /**
|
|
|
+ * 速度不能为0, 此处的速度应该是按照设置的速度而不是校准后的速度,否则mp3速度不对
|
|
|
+ */
|
|
|
+ let beatSpeed =
|
|
|
+ (state.isSpecialBookCategory
|
|
|
+ ? getTimeByBeatUnit(beatUnit, measureSpeed, iterator.currentMeasure.activeTimeSignature.Denominator)
|
|
|
+ : baseSpeed) || 1
|
|
|
+ let speed = (state.isSpecialBookCategory ? measureSpeed : baseSpeed) || 1
|
|
|
+ // console.log('曲谱设置的速度', { base: getTimeByBeatUnit(beatUnit, measureSpeed, iterator.currentMeasure.activeTimeSignature.Denominator), beatSpeed, speed})
|
|
|
+ gradualChange = iterator.currentMeasure.speedInfo || gradualChange
|
|
|
+ gradualSpeed = osmd.sheet.soundTempos?.get(note.sourceMeasure.measureListIndex) || gradualSpeed
|
|
|
+ if (!gradualSpeed || gradualSpeed.length < 2) {
|
|
|
+ gradualSpeed = createSpeedInfo(gradualChange, speed)
|
|
|
+ }
|
|
|
/**
|
|
|
* 渐变速度逻辑如下:
|
|
|
* 1. 获取渐变关键词,记录开始区间、结束区间、渐变整体结束;
|
|
@@ -275,12 +301,82 @@ export const getAllNodes = (osmd: any) => {
|
|
|
* 3. 按照比例计算下一个音符的速度;
|
|
|
* 4. 合奏曲目这里需要处理一下,因为音符位置可能不太相同,理想的情况是每个分谱指定结束时间.
|
|
|
*/
|
|
|
- let beatSpeed =
|
|
|
+ let gradualLength = 0
|
|
|
+ const measureListIndex = iterator.currentMeasure.measureListIndex
|
|
|
+ if (state.gradualTimes && Object.keys(state.gradualTimes).length > 0) {
|
|
|
+ const withInRangeNote = state.gradual.find((item, index) => {
|
|
|
+ const nextItem: any = state.gradual[index + 1]
|
|
|
+ return (
|
|
|
+ item[0].measureIndex <= measureListIndex &&
|
|
|
+ item[1]?.measureIndex! >= measureListIndex &&
|
|
|
+ (!nextItem || nextItem?.[0].measureIndex !== measureListIndex)
|
|
|
+ )
|
|
|
+ })
|
|
|
+ if (!withInRangeNote) {
|
|
|
+ useGradualTime = 0
|
|
|
+ }
|
|
|
+ const [first, last] = withInRangeNote || []
|
|
|
+ if (first && last) {
|
|
|
+ // 小节数量
|
|
|
+ const continuous = last.measureIndex - first.measureIndex
|
|
|
+ // 开始小节内
|
|
|
+ const inTheFirstMeasure = first.closedMeasureIndex == measureListIndex && si >= first.noteInMeasureIndex
|
|
|
+ // 结束小节内
|
|
|
+ const inTheLastMeasure = last.closedMeasureIndex === measureListIndex && si < last.noteInMeasureIndex
|
|
|
+ // 范围内小节
|
|
|
+ const inFiestOrLastMeasure =
|
|
|
+ first.closedMeasureIndex !== measureListIndex && last.closedMeasureIndex !== measureListIndex
|
|
|
+ if (inTheFirstMeasure || inTheLastMeasure || inFiestOrLastMeasure) {
|
|
|
+ const startTime = state.gradualTimes[first.measureIndex]
|
|
|
+ const endTime = state.gradualTimes[last.measureIndex]
|
|
|
+ if (startTime && endTime) {
|
|
|
+ const times =
|
|
|
+ continuous - first.leftDuration / first.allDuration + last.leftDuration / last.allDuration
|
|
|
+ const diff = dayjs(tranTime(endTime)).diff(dayjs(tranTime(startTime)), 'millisecond')
|
|
|
+ gradualLength = ((noteRealValue / vRealValue / times) * diff) / 1000
|
|
|
+ useGradualTime += gradualLength
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (
|
|
|
+ gradualChange &&
|
|
|
+ gradualSpeed &&
|
|
|
+ (gradualChange.startXmlNoteIndex === si || gradualChangeIndex > 0)
|
|
|
+ ) {
|
|
|
+ const startSpeed = gradualSpeed[0] - (gradualSpeed[1] - gradualSpeed[0])
|
|
|
+ const { resetXmlNoteIndex, endXmlNoteIndex } = gradualChange
|
|
|
+ const noteDiff = endXmlNoteIndex
|
|
|
+ let stepSpeed = (gradualSpeed[gradualSpeed.length - 1] - startSpeed) / noteDiff
|
|
|
+ stepSpeed = note.DotsXml ? stepSpeed / 1.5 : stepSpeed
|
|
|
+ if (gradualChangeIndex < noteDiff) {
|
|
|
+ const tempSpeed = Math.ceil(speed + stepSpeed * gradualChangeIndex)
|
|
|
+ let tmpSpeed = getTimeByBeatUnit(
|
|
|
+ beatUnit,
|
|
|
+ tempSpeed,
|
|
|
+ iterator.currentMeasure.activeTimeSignature.Denominator
|
|
|
+ )
|
|
|
+ const maxLength = (wholeValue + numerator / denominator) * vDenominator * (60 / tmpSpeed)
|
|
|
+ speed += Math.ceil(stepSpeed * (gradualChangeIndex + 1))
|
|
|
+ tmpSpeed = getTimeByBeatUnit(beatUnit, speed, iterator.currentMeasure.activeTimeSignature.Denominator)
|
|
|
+ const minLength = (wholeValue + numerator / denominator) * vDenominator * (60 / tmpSpeed)
|
|
|
+ gradualLength = (maxLength + minLength) / 2
|
|
|
+ } else if (resetXmlNoteIndex > gradualChangeIndex) {
|
|
|
+ speed = allNotes[i - 1]?.speed
|
|
|
+ }
|
|
|
+ beatSpeed =
|
|
|
(state.isSpecialBookCategory
|
|
|
- ? getTimeByBeatUnit(beatUnit, measureSpeed, iterator.currentMeasure.activeTimeSignature.Denominator)
|
|
|
+ ? getTimeByBeatUnit(beatUnit, speed, iterator.currentMeasure.activeTimeSignature.Denominator)
|
|
|
: baseSpeed) || 1
|
|
|
- let speed = (state.isSpecialBookCategory ? measureSpeed : baseSpeed) || 1
|
|
|
- // console.log('曲谱设置的速度', { isTeshu:state.isSpecialBookCategory, beatSpeed, speed})
|
|
|
+ const isEnd = !(gradualChangeIndex < noteDiff) && !(resetXmlNoteIndex > gradualChangeIndex)
|
|
|
+ gradualChangeIndex++
|
|
|
+ // console.log(gradualChangeIndex)
|
|
|
+ if (isEnd) {
|
|
|
+ gradualChangeIndex = 0
|
|
|
+ gradualChange = undefined
|
|
|
+ gradualSpeed = undefined
|
|
|
+ stepSpeeds = []
|
|
|
+ }
|
|
|
+ }
|
|
|
if (i === 0) {
|
|
|
fixtime += getFixTime(beatSpeed)
|
|
|
}
|
|
@@ -291,7 +387,9 @@ export const getAllNodes = (osmd: any) => {
|
|
|
// vDenominator *
|
|
|
// (60 / beatSpeed)
|
|
|
//管乐迷计算时值方法
|
|
|
- let noteLength = Math.min(vRealValue, noteRealValue) * formatBeatUnit(beatUnit) * (60 / beatSpeed)
|
|
|
+ let noteLength = gradualLength
|
|
|
+ ? gradualLength
|
|
|
+ : Math.min(vRealValue, noteRealValue) * formatBeatUnit(beatUnit) * (60 / beatSpeed)
|
|
|
const measureLength = vRealValue * vDenominator * (60 / beatSpeed)
|
|
|
// 单独处理个别的声部
|
|
|
if (['Piano'].includes(state.activeDetail?.code)) {
|
|
@@ -317,6 +415,7 @@ export const getAllNodes = (osmd: any) => {
|
|
|
}
|
|
|
// 处理附点时长不正确问题
|
|
|
if (note.DotsXml && note.tuplet) {
|
|
|
+ console.log('处理附点时长不正确问题')
|
|
|
noteLength = noteLength * 1.5
|
|
|
}
|
|
|
// 后倚音通过跳过的方式实现
|
|
@@ -657,7 +756,8 @@ export const getIndex = (times: any[], currentTime: Number) => {
|
|
|
}
|
|
|
|
|
|
export const getSlursNote = (_note: any, pos?: 'start' | 'end') => {
|
|
|
- const note: any = state.times.find((n: any) => n.NoteToGraphicalNoteObjectId == _note.NoteToGraphicalNoteObjectId) || {}
|
|
|
+ const note: any =
|
|
|
+ state.times.find((n: any) => n.NoteToGraphicalNoteObjectId == _note.NoteToGraphicalNoteObjectId) || {}
|
|
|
let itemNote = pos === 'end' ? note.noteElement.slurs[0]?.endNote : note.noteElement.slurs[0]?.startNote
|
|
|
// console.log("🚀 ~ itemNote", itemNote, note)
|
|
|
if (!itemNote) return undefined
|
|
@@ -809,7 +909,7 @@ export const getDuration = (osmd: any): any => {
|
|
|
return {
|
|
|
...formatDuration(activeTimeSignature, duration),
|
|
|
tempoInBPM,
|
|
|
- beatUnit
|
|
|
+ beatUnit,
|
|
|
}
|
|
|
}
|
|
|
}
|