Selaa lähdekoodia

休止符不亮或者闪一下规则优化

黄琪勇 7 kuukautta sitten
vanhempi
commit
ea495edaae
2 muutettua tiedostoa jossa 52 lisäystä ja 20 poistoa
  1. 51 20
      src/helpers/formateMusic.ts
  2. 1 0
      src/page-instrument/view-detail/index.tsx

+ 51 - 20
src/helpers/formateMusic.ts

@@ -1215,6 +1215,7 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			// console.log('si',si,i)
 			// console.log(note.sourceMeasure.MeasureNumberXML,note,svgElement, NoteRealValue, measureLength)
 			if (allNotes.length && allNotes[allNotes.length - 1].relativeTime === relativeTime) {
+				i++
 				continue;
 			}
 			// console.log(iterator.currentMeasure)
@@ -1277,39 +1278,55 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			/**
 			 * evxml的曲子,如果曲谱xml中带有times信息,则音符时值优先取times中的值
 			 * 曲子:1795013295024062466(春暖花开),如果音符有times信息,休止符没有times信息,此种规则是认为休止符不参与时值计算的,需要过滤掉该休止符
-			 * TODO:需要考虑唱名怎么处理,唱名是xml有多少个音符,就需要唱多少个,不能剔除
 			 */
+			let evNoteStartTime = 0, evNoteEndTime = 0;
 			if (state.isEvxml && note.isRestFlag && note?.noteTimeInfo?.length === 0 && state.xmlHasTimes ) {
-				const idx = _notes.findIndex(item=>item.note === note);
-				let nextNoteTimes = _notes[idx+1]?.note?.noteTimeInfo?.[0]?.begin*1000 
-				let preNoteTImes = _notes[idx-1]?.note?.noteTimeInfo?.[0]?.end*1000
-				// 当下一个音符也没有时间的时候,再往下一个找
-				if(!nextNoteTimes && nextNoteTimes!==0){
-					let nextIndex = idx + 2
-					while(!nextNoteTimes && nextIndex<_notes.length){
-						nextNoteTimes = _notes[nextIndex]?.note?.noteTimeInfo?.[0]?.begin*1000
-						nextIndex ++
-					}
-					// 当最后音符就是没有打时间的休止小节,可能nextNoteTimes时间找不到,目前没有处理
+				// 找出这个音符前面音符的结束时间
+				let preNoteTImes = allNotes[allNotes.length - 1]?.endtime*1000
+				if(!preNoteTImes){
+					preNoteTImes = Math.max(fixtime - noteLength, 0)*1000 //如果前一个音符没有结束时间,证明这个音符是第一个音符没有打时间,所以往前奏里面找补
 				}
-				if(!preNoteTImes && preNoteTImes!==0){
-					let preIndex = idx - 2
-					while(!preNoteTImes && preIndex>-1){
-						preNoteTImes = _notes[preIndex]?.note?.noteTimeInfo?.[0]?.end*1000
-						preIndex --
+				// 找出这个音符后面音符的开始时间
+				let nextI = i
+				let nextNoteTimes
+				// 多个连续的没有打时间的音符 需要平分时值
+				const notesRatio = []
+				while (!nextNoteTimes && nextI<_notes.length) {
+					notesRatio.push(_notes[nextI].note.length.realValue)
+					nextI++
+					if(_notes[nextI]?.note){ // 有可能_notes里面没有这个音符
+						nextNoteTimes = fliterNotesTime(_notes[nextI].note, preNoteTImes)
 					}
-					// 当没有找到preNoteTImes的时候 赋值为0 (当第一个音符就是没有打时间的休止小节会出现这种情况)
-					preNoteTImes || (preNoteTImes = 0)
 				}
+				// 当最后音符就是没有打时间的音符,可能nextNoteTimes时间找不到时候取上个音符的结束时间加上这个音符的时间
+				if(!nextNoteTimes){
+					nextNoteTimes = preNoteTImes + noteLength*1000
+				}
+				// 判断有没有首位连续 首位连续的时候删掉这个音符
 				const allowRange = Math.abs(nextNoteTimes - preNoteTImes)< 10;
 				if (allowRange) {
 					note.maxNoteNum = note.maxNoteNum - 1;
 					// 唱名时间补齐,当删除这个音符的时候,上个音符的持续时间要加上这个音符的时间
 					allNotes[allNotes.length - 1].noteLengthTime += noteLength
+					i++
 					continue;
+				}else{
+					// 当多个连续的休止符没有打时间的时候 根据音符平均分配
+					if(notesRatio.length > 1){
+						const sum = notesRatio.reduce((acc:number, curr:number) => acc + curr, 0)
+						nextNoteTimes = (nextNoteTimes - preNoteTImes) * notesRatio[0] / sum + preNoteTImes
+					}
+					evNoteEndTime = nextNoteTimes/1000
+					evNoteStartTime = preNoteTImes/1000
+					// 当这个音符计算出来的时值大于本身这个音符的时值时候,取这个音符的长度,防止有前奏和间奏的时候,计算音符持续时长过长
+					if(evNoteEndTime - evNoteStartTime > noteLength){
+						evNoteEndTime = evNoteStartTime + noteLength
+					}
+					if (evNoteStartTime) {
+						relativeTime = evNoteStartTime - fixtime
+					}
 				}
 			}
-			let evNoteStartTime = 0, evNoteEndTime = 0;
 			if (state.isEvxml && note?.noteTimeInfo?.length ) {
 				let idx = noteIds.filter((item: any) => item === svgElement?.attrs.id)?.length || 0;
 				// 如果是合并的小节的休止符
@@ -1733,4 +1750,18 @@ export const compatibleXmlPitchVoice = (xmlParse: any) => {
 		}
 		(window as any).xmlNeedAdjustVoice = xmlNeedAdjustVoice
 	}
+}
+
+// 筛选出这个音符中的值(比前一个音符时值大的值)
+function fliterNotesTime(note:any, preTime:number):undefined|number {
+	// 音符可能涉及多遍歌词,所以这里要找到对应的times
+	if(note?.noteTimeInfo?.length){
+		const timeObj = note?.noteTimeInfo.find((value:any) => {
+			const beginTime = value?.begin*1000 || 0
+			return beginTime > preTime || Math.abs(beginTime - preTime)< 10  //差值在10毫秒之内
+		})
+		return timeObj?.begin*1000
+	}else{
+		return undefined
+	}
 }

+ 1 - 0
src/page-instrument/view-detail/index.tsx

@@ -326,6 +326,7 @@ export default defineComponent({
       try{
         handleRendered(osmd)
       }catch(err:any){
+        console.error(err);
         // 需要向外面(iframe)派发计时器数据的时候触发
         if(query.isbeatTimes){
           console.log("webApi_beatTimes",err)