|
@@ -17,6 +17,11 @@ const browserInfo = browser();
|
|
dayjs.extend(duration);
|
|
dayjs.extend(duration);
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * 需要隐藏的中文速度文本
|
|
|
|
+ */
|
|
|
|
+const hideSpeedWords: string[] = ["中速"];
|
|
|
|
+
|
|
|
|
+/**
|
|
* 获取节拍器的时间
|
|
* 获取节拍器的时间
|
|
* @param speed 速度
|
|
* @param speed 速度
|
|
* @param firstMeasure 曲谱第一个小节
|
|
* @param firstMeasure 曲谱第一个小节
|
|
@@ -378,6 +383,7 @@ export const onlyVisible = (xml: string, partIndex: number): string => {
|
|
// console.log(visiblePartInfo, partIndex)
|
|
// console.log(visiblePartInfo, partIndex)
|
|
// 根据后台已选择的分轨筛选出能切换的声轨
|
|
// 根据后台已选择的分轨筛选出能切换的声轨
|
|
state.partListNames = partListNames;
|
|
state.partListNames = partListNames;
|
|
|
|
+ // console.log('分轨名称',state.partListNames)
|
|
if (visiblePartInfo) {
|
|
if (visiblePartInfo) {
|
|
const id = visiblePartInfo.getAttribute("id");
|
|
const id = visiblePartInfo.getAttribute("id");
|
|
Array.from(parts).forEach((part: any) => {
|
|
Array.from(parts).forEach((part: any) => {
|
|
@@ -615,6 +621,7 @@ export const formatZoom = (num = 1) => {
|
|
*/
|
|
*/
|
|
export const formatXML = (xml: string, xmlUrl?: string): string => {
|
|
export const formatXML = (xml: string, xmlUrl?: string): string => {
|
|
if (!xml) return "";
|
|
if (!xml) return "";
|
|
|
|
+
|
|
const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
|
|
const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
|
|
const measures = Array.from(xmlParse.getElementsByTagName("measure"));
|
|
const measures = Array.from(xmlParse.getElementsByTagName("measure"));
|
|
const repeats: any = Array.from(xmlParse.querySelectorAll('repeat'));
|
|
const repeats: any = Array.from(xmlParse.querySelectorAll('repeat'));
|
|
@@ -624,6 +631,7 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
|
|
// 解析处理evxml
|
|
// 解析处理evxml
|
|
if (state.isEvxml) {
|
|
if (state.isEvxml) {
|
|
analyzeEvxml(xmlParse, xmlUrl);
|
|
analyzeEvxml(xmlParse, xmlUrl);
|
|
|
|
+ customizationXml(xmlParse);
|
|
}
|
|
}
|
|
// const words: any = xmlParse.getElementsByTagName("words");
|
|
// const words: any = xmlParse.getElementsByTagName("words");
|
|
// for (const word of words) {
|
|
// for (const word of words) {
|
|
@@ -655,11 +663,30 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
|
|
// if (note.getElementsByTagName("space").length && !note.getElementsByTagName("duration").length) {
|
|
// if (note.getElementsByTagName("space").length && !note.getElementsByTagName("duration").length) {
|
|
// measure.removeChild(note);
|
|
// measure.removeChild(note);
|
|
// }
|
|
// }
|
|
- if (!note.getElementsByTagName("duration").length || (note.getElementsByTagName("duration").length && note.getElementsByTagName("duration")[0]?.textContent == 0)) {
|
|
|
|
- measure.removeChild(note);
|
|
|
|
|
|
+ // 非倚音音符
|
|
|
|
+ if (!note.getElementsByTagName("grace").length) {
|
|
|
|
+ if (!note.getElementsByTagName("duration").length || (note.getElementsByTagName("duration").length && note.getElementsByTagName("duration")[0]?.textContent == 0)) {
|
|
|
|
+ measure.removeChild(note);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
+ // 如果有特殊中文速度文本,需要删除
|
|
|
|
+ const reg = new RegExp("[\\u4E00-\\u9FFF]+", "g");
|
|
|
|
+ if (measure.getElementsByTagName("words").length && state.isEvxml) {
|
|
|
|
+ const wordList = Array.from(measure.getElementsByTagName("words")) || [];
|
|
|
|
+ wordList.forEach((word: any) => {
|
|
|
|
+ // TODO:删除妙极客曲子无意义的words
|
|
|
|
+ // wordArr?.push(word?.textContent)
|
|
|
|
+ if (word?.textContent && reg.test(word?.textContent) && word?.parentNode?.parentNode) {
|
|
|
|
+ measure.removeChild(word.parentNode.parentNode);
|
|
|
|
+ // deleteWordArr?.push(word?.textContent)
|
|
|
|
+ }
|
|
|
|
+ // if(hideSpeedWords.includes(word?.textContent) && word?.parentNode?.parentNode) {
|
|
|
|
+ // measure.removeChild(word.parentNode.parentNode);
|
|
|
|
+ // }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
if (measure.getElementsByTagName("note").length === 0) {
|
|
if (measure.getElementsByTagName("note").length === 0) {
|
|
const forwardTimeElement = measure.getElementsByTagName("forward")[0]?.getElementsByTagName("duration")[0];
|
|
const forwardTimeElement = measure.getElementsByTagName("forward")[0]?.getElementsByTagName("duration")[0];
|
|
if (forwardTimeElement) {
|
|
if (forwardTimeElement) {
|
|
@@ -745,6 +772,8 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
let staveNoteIndex = 0;
|
|
let staveNoteIndex = 0;
|
|
let staveIndex = 0;
|
|
let staveIndex = 0;
|
|
|
|
|
|
|
|
+ let preNoteEndTime = 0; // 上一个音符的结束时间
|
|
|
|
+
|
|
const _notes = [] as any[];
|
|
const _notes = [] as any[];
|
|
if (state.gradualTimes) {
|
|
if (state.gradualTimes) {
|
|
console.log("后台设置的渐慢小节时间", state.gradual, state.gradualTimes);
|
|
console.log("后台设置的渐慢小节时间", state.gradual, state.gradualTimes);
|
|
@@ -754,6 +783,8 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
const currentTimes = [] as any[];
|
|
const currentTimes = [] as any[];
|
|
let isSetNextNoteReal = false;
|
|
let isSetNextNoteReal = false;
|
|
let differFrom = 0;
|
|
let differFrom = 0;
|
|
|
|
+ // let testIdx = 0;
|
|
|
|
+ let repeatIdx = 0; // 循环的次数
|
|
while (!iterator.EndReached) {
|
|
while (!iterator.EndReached) {
|
|
// console.log({ ...iterator });
|
|
// console.log({ ...iterator });
|
|
const voiceEntries = iterator.CurrentVoiceEntries?.[0] ? [iterator.CurrentVoiceEntries?.[0]] : [];
|
|
const voiceEntries = iterator.CurrentVoiceEntries?.[0] ? [iterator.CurrentVoiceEntries?.[0]] : [];
|
|
@@ -837,10 +868,18 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
}
|
|
}
|
|
|
|
|
|
iterator.moveToNextVisibleVoiceEntry(false);
|
|
iterator.moveToNextVisibleVoiceEntry(false);
|
|
|
|
+ // 从头开始循环,repeatIdx标记+1
|
|
|
|
+ if (iterator.backJumpOccurred) {
|
|
|
|
+ repeatIdx += 1;
|
|
|
|
+ }
|
|
|
|
+ iterator.repeatIdx = repeatIdx;
|
|
|
|
+ // console.log('小节',testIdx,iterator.repeatIdx,iterator.EndReached,iterator.currentMeasureIndex,iterator.backJumpOccurred,iterator.forwardJumpOccurred)
|
|
|
|
+ // testIdx += 1;
|
|
}
|
|
}
|
|
// 是否是变速的曲子
|
|
// 是否是变速的曲子
|
|
const hasVaryingSpeed = _notes.some((item: any) => item.measuresTempoInBPM !== _notes[0].measuresTempoInBPM)
|
|
const hasVaryingSpeed = _notes.some((item: any) => item.measuresTempoInBPM !== _notes[0].measuresTempoInBPM)
|
|
- console.log('变速曲子',hasVaryingSpeed)
|
|
|
|
|
|
+ console.log('变速曲子',hasVaryingSpeed, _notes)
|
|
|
|
+ let noteIds: any = [];
|
|
// let voicesBBox: any = null;
|
|
// let voicesBBox: any = null;
|
|
for (let { note, iterator, currentTime, isDouble, isMutileSubject } of _notes) {
|
|
for (let { note, iterator, currentTime, isDouble, isMutileSubject } of _notes) {
|
|
if (note) {
|
|
if (note) {
|
|
@@ -920,6 +959,12 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
}
|
|
}
|
|
|
|
|
|
let relativeTime = usetime;
|
|
let relativeTime = usetime;
|
|
|
|
+
|
|
|
|
+ // 妙极客的曲子,修复有的音符有times,有的音符没有times导致的,累计时长错误问题
|
|
|
|
+ if (state.isEvxml && relativeTime < preNoteEndTime - fixtime) {
|
|
|
|
+ relativeTime = preNoteEndTime - fixtime
|
|
|
|
+ }
|
|
|
|
+
|
|
let beatSpeed = 0;
|
|
let beatSpeed = 0;
|
|
// 速度不能为0 此处的速度应该是按照设置的速度而不是校准后的速度,否则mp3速度不对
|
|
// 速度不能为0 此处的速度应该是按照设置的速度而不是校准后的速度,否则mp3速度不对
|
|
if (measureSpeed !== baseSpeed && !hasVaryingSpeed) {
|
|
if (measureSpeed !== baseSpeed && !hasVaryingSpeed) {
|
|
@@ -1094,6 +1139,21 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
// console.log(note.tie)
|
|
// console.log(note.tie)
|
|
// console.log('👀看看endtime', duration, relaEndtime, fixtime, i)
|
|
// console.log('👀看看endtime', duration, relaEndtime, fixtime, i)
|
|
// console.log('频率',note?.pitch?.frequency,i)
|
|
// console.log('频率',note?.pitch?.frequency,i)
|
|
|
|
+ /**
|
|
|
|
+ * evxml的曲子,如果曲谱xml中带有times信息,则音符时值优先取times中的值
|
|
|
|
+ */
|
|
|
|
+ let evNoteStartTime = 0, evNoteEndTime = 0;
|
|
|
|
+ if (state.isEvxml && note?.noteTimeInfo?.length) {
|
|
|
|
+ const idx = noteIds.filter((item: any) => item === svgElement?.attrs.id)?.length || 0
|
|
|
|
+ evNoteStartTime = note?.noteTimeInfo[idx]?.begin
|
|
|
|
+ evNoteEndTime = note?.noteTimeInfo[idx]?.end
|
|
|
|
+ if (evNoteStartTime) {
|
|
|
|
+ relativeTime = evNoteStartTime - fixtime
|
|
|
|
+ // usetime = evNoteStartTime - fixtime
|
|
|
|
+ }
|
|
|
|
+ // usetime = evNoteStartTime - fixtime
|
|
|
|
+ }
|
|
|
|
+ svgElement?.attrs.id && noteIds.push(svgElement?.attrs.id)
|
|
|
|
|
|
const nodeDetail = {
|
|
const nodeDetail = {
|
|
isStaccato: note.voiceEntry.isStaccato(),
|
|
isStaccato: note.voiceEntry.isStaccato(),
|
|
@@ -1122,8 +1182,8 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
note: note.halfTone + 12, // see issue #224
|
|
note: note.halfTone + 12, // see issue #224
|
|
fixtime, // 弱起补充的时间
|
|
fixtime, // 弱起补充的时间
|
|
relativeTime: retain(relativeTime),
|
|
relativeTime: retain(relativeTime),
|
|
- time: retain(relativeTime + fixtime), // 开始播放的时间
|
|
|
|
- endtime: retain(relaEndtime + fixtime), // 播放完成的时间
|
|
|
|
|
|
+ time: state.isEvxml && evNoteStartTime ? retain(evNoteStartTime) : retain(relativeTime + fixtime), // 开始播放的时间
|
|
|
|
+ endtime: state.isEvxml && evNoteEndTime ? retain(evNoteEndTime) : retain(relaEndtime + fixtime), // 播放完成的时间
|
|
relaEndtime: retain(relaEndtime),
|
|
relaEndtime: retain(relaEndtime),
|
|
realValue,
|
|
realValue,
|
|
halfTone: note.halfTone,
|
|
halfTone: note.halfTone,
|
|
@@ -1141,7 +1201,22 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
totalMultipleRestMeasures, // 当前小节总的合并小节数
|
|
totalMultipleRestMeasures, // 当前小节总的合并小节数
|
|
measureSpeed, // 小节速度
|
|
measureSpeed, // 小节速度
|
|
maxNoteNum: note.maxNoteNum, // 当前小节音符最多的分轨的音符数量
|
|
maxNoteNum: note.maxNoteNum, // 当前小节音符最多的分轨的音符数量
|
|
|
|
+ repeatIdx: iterator.repeatIdx, // 标记是第几遍循环,从0开始
|
|
};
|
|
};
|
|
|
|
+ // 如果是妙极客的曲子,并且第二遍循环播放需要等待时间,并且是第二遍循环的第一个小节的第一个音符
|
|
|
|
+ // if (state.isEvxml && state.secondEvXmlBeginTime && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === 1 && nodeDetail.noteId === 0) {
|
|
|
|
+ // nodeDetail.time = nodeDetail.time + state.secondEvXmlBeginTime;
|
|
|
|
+ // nodeDetail.endtime = nodeDetail.endtime + state.secondEvXmlBeginTime;
|
|
|
|
+ // usetime = usetime + state.secondEvXmlBeginTime;
|
|
|
|
+ // relativeTime = relativeTime + state.secondEvXmlBeginTime;
|
|
|
|
+ // }
|
|
|
|
+ if (state.isEvxml && nodeDetail.repeatIdx && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === 1 && nodeDetail.noteId === 0) {
|
|
|
|
+ const currentWaitTime = state.evXmlBeginArr[nodeDetail.repeatIdx] || 0;
|
|
|
|
+ nodeDetail.time = nodeDetail.time + currentWaitTime;
|
|
|
|
+ nodeDetail.endtime = nodeDetail.endtime + currentWaitTime;
|
|
|
|
+ usetime = usetime + currentWaitTime;
|
|
|
|
+ relativeTime = relativeTime + currentWaitTime;
|
|
|
|
+ }
|
|
nodeDetail.realKey = formatRealKey(note.halfTone - fixedKey * 12, nodeDetail);
|
|
nodeDetail.realKey = formatRealKey(note.halfTone - fixedKey * 12, nodeDetail);
|
|
nodeDetail.duration = nodeDetail.endtime - nodeDetail.time;
|
|
nodeDetail.duration = nodeDetail.endtime - nodeDetail.time;
|
|
let tickables = activeVerticalMeasureList[0]?.vfVoices["1"]?.tickables || [];
|
|
let tickables = activeVerticalMeasureList[0]?.vfVoices["1"]?.tickables || [];
|
|
@@ -1150,6 +1225,7 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
}
|
|
}
|
|
// console.log(note.sourceMeasure.MeasureNumberXML, note.sourceMeasure.verticalSourceStaffEntryContainers.length)
|
|
// console.log(note.sourceMeasure.MeasureNumberXML, note.sourceMeasure.verticalSourceStaffEntryContainers.length)
|
|
// console.log('👀看看endtime', nodeDetail.duration, relaEndtime, fixtime, i)
|
|
// console.log('👀看看endtime', nodeDetail.duration, relaEndtime, fixtime, i)
|
|
|
|
+ // console.log('音符时间',nodeDetail.i,nodeDetail.time,nodeDetail.endtime)
|
|
tickables = tickables.filter((tickable: any) => tickable.attrs?.type !== "GhostNote")
|
|
tickables = tickables.filter((tickable: any) => tickable.attrs?.type !== "GhostNote")
|
|
const maxNum = (state.isCombineRender && note.maxNoteNum) ? note.maxNoteNum : tickables.length;
|
|
const maxNum = (state.isCombineRender && note.maxNoteNum) ? note.maxNoteNum : tickables.length;
|
|
nodeDetail.noteLength = maxNum || 1;
|
|
nodeDetail.noteLength = maxNum || 1;
|
|
@@ -1167,11 +1243,14 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
|
|
relaMeasureLength = 0;
|
|
relaMeasureLength = 0;
|
|
measures = [];
|
|
measures = [];
|
|
}
|
|
}
|
|
|
|
+ preNoteEndTime = nodeDetail.endtime;
|
|
}
|
|
}
|
|
i++;
|
|
i++;
|
|
}
|
|
}
|
|
// 按照时间轴排序
|
|
// 按照时间轴排序
|
|
const sortArray = allNotes.sort((a, b) => a.relativeTime - b.relativeTime).map((item, index) => ({ ...item, i: index }));
|
|
const sortArray = allNotes.sort((a, b) => a.relativeTime - b.relativeTime).map((item, index) => ({ ...item, i: index }));
|
|
|
|
+ // const sortArray = allNotes.sort((a, b) => a.time - b.time).map((item, index) => ({ ...item, i: index }));
|
|
|
|
+ // const sortArray = allNotes.map((item, index) => ({ ...item, i: index }));
|
|
console.timeEnd("音符跑完时间");
|
|
console.timeEnd("音符跑完时间");
|
|
try {
|
|
try {
|
|
osmd.cursor.reset();
|
|
osmd.cursor.reset();
|
|
@@ -1258,19 +1337,118 @@ export const verifyCanRepeat = (startNum: number, endNum: number) => {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 处理妙极客xml谱面
|
|
|
|
+const customizationXml = (xmlParse: any) => {
|
|
|
|
+ const credits: any = Array.from(xmlParse.querySelectorAll('credit'));
|
|
|
|
+ const creators: any = Array.from(xmlParse.querySelectorAll('creator'));
|
|
|
|
+ const graces: any = Array.from(xmlParse.querySelectorAll('grace'));
|
|
|
|
+ const measures: any[] = Array.from(xmlParse.getElementsByTagName("measure"));
|
|
|
|
+ const notes: any[] = Array.from(xmlParse.getElementsByTagName("note"));
|
|
|
|
+
|
|
|
|
+ // 获取音符最多的歌词数,用于自定义循环播放次数
|
|
|
|
+ let maxLyricNum = 0;
|
|
|
|
+ if (notes && notes.length) {
|
|
|
|
+ for (const note of notes) {
|
|
|
|
+ if (maxLyricNum < note.getElementsByTagName("lyric").length) {
|
|
|
|
+ maxLyricNum = note.getElementsByTagName("lyric").length
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ state.maxLyricNum = maxLyricNum;
|
|
|
|
+ // state.osmd.EngravingRules.DYCustomRepeatCount = maxLyricNum;
|
|
|
|
+ ;(window as any).DYCustomRepeatCount = state.maxLyricNum;
|
|
|
|
+ console.log('歌词次数',maxLyricNum)
|
|
|
|
+
|
|
|
|
+ if (credits && credits.length) {
|
|
|
|
+ for (const credit of credits) {
|
|
|
|
+ if (credit.getElementsByTagName("credit-type")?.[0]?.textContent === 'lyricist') {
|
|
|
|
+ const creditWord = credit.getElementsByTagName("credit-words")
|
|
|
|
+ creditWord?.[0].setAttribute('justify', 'right')
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (creators && creators.length) {
|
|
|
|
+ for (const creator of creators) {
|
|
|
|
+ if (creator.getAttribute('type') === 'lyricist') {
|
|
|
|
+ // creator.textContent = '测试一下1';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 妙极客xml的倚音(grace)标签需要加上slash=yes属性
|
|
|
|
+ if (graces && graces.length) {
|
|
|
|
+ for (const grace of graces) {
|
|
|
|
+ grace?.setAttribute('slash','yes');
|
|
|
|
+ // console.log(grace,'倚音')
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 妙极客xml部分小节没有音符,只有Segno,该小节不需要渲染,表示的是反复标记
|
|
|
|
+ for (const measure of measures) {
|
|
|
|
+ const hasNote = measure.getElementsByTagName("note").length;
|
|
|
|
+ const hasSegno = measure.getElementsByTagName("segno").length;
|
|
|
|
+ const sounds = Array.from(measure.getElementsByTagName("sound"));
|
|
|
|
+ const hasSoundSegno = sounds.some((item: any) => item.getAttribute('segno') === 'segno' );
|
|
|
|
+ if (!hasNote && hasSegno && hasSoundSegno) {
|
|
|
|
+ const parent = measure.parentNode;
|
|
|
|
+ parent.removeChild(measure);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * bug: #10289,曲目:1782672015612725196、1788040971888537602
|
|
|
|
+ * 妙极客xml,多遍歌词循环的曲目,如果没有repeat标签,需要加上repeat标签
|
|
|
|
+ * */
|
|
|
|
+ if (maxLyricNum > 1) {
|
|
|
|
+ const hasRepeat = xmlParse.querySelectorAll('repeat').length > 0
|
|
|
|
+ if (!hasRepeat) {
|
|
|
|
+ const lastMeasure = measures.last();
|
|
|
|
+ if (lastMeasure.getElementsByTagName('barline').length) {
|
|
|
|
+ const barlineDom = lastMeasure.getElementsByTagName('barline')[0]
|
|
|
|
+ barlineDom.innerHTML = barlineDom.innerHTML + `<repeat direction="backward" />`;
|
|
|
|
+ } else {
|
|
|
|
+ lastMeasure.innerHTML = lastMeasure.innerHTML + `
|
|
|
|
+ <barline location="right">
|
|
|
|
+ <bar-style>light-heavy</bar-style>
|
|
|
|
+ <repeat direction="backward" />
|
|
|
|
+ </barline>`
|
|
|
|
+ }
|
|
|
|
+ // console.log(lastMeasure)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
// 计算evxml的起始播放时间
|
|
// 计算evxml的起始播放时间
|
|
const analyzeEvxml = (xmlParse: any, xmlUrl?: string) => {
|
|
const analyzeEvxml = (xmlParse: any, xmlUrl?: string) => {
|
|
// xml拍号数
|
|
// xml拍号数
|
|
const xmlNum = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[0]?.getAttribute('num');
|
|
const xmlNum = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[0]?.getAttribute('num');
|
|
|
|
+ const denNum = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[0]?.getAttribute('den');
|
|
|
|
+ const xmlNum2 = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[1]?.getAttribute('num');
|
|
|
|
+ const denNum2 = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[1]?.getAttribute('den');
|
|
|
|
+ const timeGaps: any = xmlParse.getElementsByTagName("timegap")?.length ? Array.from(xmlParse.getElementsByTagName("timegap")?.[0]?.getElementsByTagName("values")?.[0]?.getElementsByTagName("item")) : [];
|
|
// 第一个音符的起始时间
|
|
// 第一个音符的起始时间
|
|
- const firstNoteBeginTime = xmlParse.getElementsByTagName("times")[0]?.getElementsByTagName("time")[0]?.getAttribute('begin');
|
|
|
|
- state.evXmlBeginTime = firstNoteBeginTime ? firstNoteBeginTime / 1000 : xmlNum ? 60 / state.originSpeed * xmlNum : 0;
|
|
|
|
- const hasTimeGap = xmlParse.getElementsByTagName("timegap").length > 0;
|
|
|
|
- const hasTimes = xmlParse.getElementsByTagName("times").length > 0;
|
|
|
|
|
|
+ const firstMeasure = xmlParse.getElementsByTagName("measure")[0];
|
|
|
|
+ if (firstMeasure) {
|
|
|
|
+ const firstNoteBeginTime = firstMeasure.getElementsByTagName("times")[0]?.getElementsByTagName("time")[0]?.getAttribute('begin');
|
|
|
|
+ state.evXmlBeginTime = firstNoteBeginTime ? firstNoteBeginTime / 1000 : xmlNum ? 60 / state.originSpeed * xmlNum * 4/denNum : 0;
|
|
|
|
+ state.secondEvXmlBeginTime = firstNoteBeginTime ? 0 : xmlNum2 ? 60 / state.originSpeed * xmlNum2 * 4/denNum2 : 0;
|
|
|
|
+ const hasTimeGap = xmlParse.getElementsByTagName("timegap").length > 0;
|
|
|
|
+ const hasTimes = xmlParse.getElementsByTagName("times").length > 0;
|
|
|
|
+
|
|
|
|
+ if (timeGaps && timeGaps.length && !firstNoteBeginTime) {
|
|
|
|
+ for (const timeGap of timeGaps) {
|
|
|
|
+ const num: any = timeGap?.getAttribute('num'), den: any = timeGap?.getAttribute('den');
|
|
|
|
+ const startTime = num ? 60 / state.originSpeed * num * 4/den : 0;
|
|
|
|
+ state.evXmlBeginArr.push(startTime)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ console.log('🚀 ~ evxml解析','有timegap:',hasTimeGap,'有times:',hasTimes,'timegap集合',state.evXmlBeginArr,'第一个timegap',state.evXmlBeginTime)
|
|
|
|
+ }
|
|
|
|
+
|
|
// if (!hasTimeGap && !hasTimes) {
|
|
// if (!hasTimeGap && !hasTimes) {
|
|
// state.noTimes.push(xmlUrl)
|
|
// state.noTimes.push(xmlUrl)
|
|
// }
|
|
// }
|
|
- console.log('🚀 ~ evxml解析','有timegap:',hasTimeGap,'有times:',hasTimes)
|
|
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|