Преглед на файлове

feat: 多遍time支持多遍循环,简谱休止符渲染规则修改

TIANYONG преди 9 месеца
родител
ревизия
69ed6ff89c
променени са 2 файла, в които са добавени 84 реда и са изтрити 65 реда
  1. 78 62
      src/helpers/customMusicScore.ts
  2. 6 3
      src/helpers/formateMusic.ts

+ 78 - 62
src/helpers/customMusicScore.ts

@@ -1100,14 +1100,26 @@ export const transferJianNote = (measure: any, divisions: number, preBeats: numb
 	const multipleXs = preBeatType / 4;
 	const notes = measure.getElementsByTagName("note")
 	for (const note of notes) {
+		// 是否需要考虑带上附点
+		let needAddDot = true;
 		const noteType = note.getElementsByTagName("type")?.[0]?.textContent || '';
 		if ((noteType === 'whole' || noteType === 'half') && note.getElementsByTagName("rest").length) {
 			// 4/4拍,3/4拍
-			if ((preBeats === 4 && preBeatType === 4) || (preBeats === 3 && preBeatType === 4)) {
+			if (preBeatType === 4) {
 				let maxNumber = noteType === 'half' ? 2 : preBeats / multipleXs;
-				// 如果二分音符带附点,需要判断处理下
-				if (note.getElementsByTagName("dot").length) {
-					maxNumber = maxNumber + 1;
+				if (noteType === 'whole') {
+					// 有可能是全休止符,但是该小节又不是整小节都休止,此时这个全休止符不能按照整小节休止来计算
+					const noteDivisions = parseInt(note.getElementsByTagName("duration")[0]?.textContent);
+					if (noteDivisions/divisions !== preBeats) {
+						maxNumber = 4;
+					} else {
+						// 满足了时值,则不需要考虑加上附点
+						needAddDot = false;
+					}
+				}
+				// 如果音符带附点,需要判断处理下
+				if (note.getElementsByTagName("dot").length && needAddDot) {
+					maxNumber = noteType === 'whole' ? maxNumber + 2 : maxNumber + 1;
 				}
 				if (!Number.isInteger(maxNumber)) {
 					return;
@@ -1158,22 +1170,7 @@ export const transferJianNote = (measure: any, divisions: number, preBeats: numb
 					measure.insertBefore(newnote2, note);
 					measure.removeChild(note);
 				} else if (noteType === 'half') {
-					const newnote = document.createElement('note');
-					newnote.innerHTML = `
-					<rest></rest>
-					<duration>${divisions+divisions/2}</duration>
-					<voice>1</voice>
-					<type>quarter</type>
-					<dot></dot>`
-					measure.insertBefore(newnote, note);
-					const newnote2 = document.createElement('note');
-					newnote2.innerHTML = `
-					<rest></rest>
-					<duration>${divisions/2}</duration>
-					<voice>1</voice>
-					<type>eighth</type>`
-					measure.insertBefore(newnote2, note);
-					measure.removeChild(note);
+					dealDotHalfNote(measure, divisions, note)
 				}
 			} else if (preBeats === 6 && preBeatType === 8) {
 				if (noteType === 'whole') {
@@ -1192,22 +1189,33 @@ export const transferJianNote = (measure: any, divisions: number, preBeats: numb
 					};
 					measure.removeChild(note);
 				} else if (noteType === 'half') {
-					const newnote = document.createElement('note');
-					newnote.innerHTML = `
+					dealDotHalfNote(measure, divisions, note)		
+				}
+			} else if (preBeats === 7 && preBeatType === 8) {
+				if (noteType === 'whole') {
+					const newnote2 = document.createElement('note');
+					newnote2.innerHTML = `
 					<rest></rest>
 					<duration>${divisions+divisions/2}</duration>
 					<voice>1</voice>
 					<type>quarter</type>
 					<dot></dot>`
-					measure.insertBefore(newnote, note);
-					const newnote2 = document.createElement('note');
-					newnote2.innerHTML = `
-					<rest></rest>
-					<duration>${divisions/2}</duration>
-					<voice>1</voice>
-					<type>eighth</type>`
-					measure.insertBefore(newnote2, note);
+					measure.insertBefore(newnote2, note);         					
+					const maxNumber = 2;
+					let quarterNoteNumber = 1;
+					while (quarterNoteNumber <= maxNumber) {
+						const newnote = document.createElement('note');
+						newnote.innerHTML = `
+						<rest></rest>
+						<duration>${divisions}</duration>
+						<voice>1</voice>
+						<type>quarter</type>`
+						measure.insertBefore(newnote, note);
+						quarterNoteNumber += 1;
+					};
 					measure.removeChild(note);
+				} else if (noteType === 'half') {
+					dealDotHalfNote(measure, divisions, note)
 				}
 			} else if (preBeats === 9 && preBeatType === 8) {
 				if (noteType === 'whole') {
@@ -1226,22 +1234,7 @@ export const transferJianNote = (measure: any, divisions: number, preBeats: numb
 					};
 					measure.removeChild(note);
 				} else if (noteType === 'half') {
-					const newnote = document.createElement('note');
-					newnote.innerHTML = `
-					<rest></rest>
-					<duration>${divisions+divisions/2}</duration>
-					<voice>1</voice>
-					<type>quarter</type>
-					<dot></dot>`
-					measure.insertBefore(newnote, note);
-					const newnote2 = document.createElement('note');
-					newnote2.innerHTML = `
-					<rest></rest>
-					<duration>${divisions/2}</duration>
-					<voice>1</voice>
-					<type>eighth</type>`
-					measure.insertBefore(newnote2, note);
-					measure.removeChild(note);
+					dealDotHalfNote(measure, divisions, note)
 				}
 			} else if (preBeats === 12 && preBeatType === 8) {
 				if (noteType === 'whole') {
@@ -1260,24 +1253,47 @@ export const transferJianNote = (measure: any, divisions: number, preBeats: numb
 					};
 					measure.removeChild(note);
 				} else if (noteType === 'half') {
-					const newnote = document.createElement('note');
-					newnote.innerHTML = `
-					<rest></rest>
-					<duration>${divisions+divisions/2}</duration>
-					<voice>1</voice>
-					<type>quarter</type>
-					<dot></dot>`
-					measure.insertBefore(newnote, note);
-					const newnote2 = document.createElement('note');
-					newnote2.innerHTML = `
-					<rest></rest>
-					<duration>${divisions/2}</duration>
-					<voice>1</voice>
-					<type>eighth</type>`
-					measure.insertBefore(newnote2, note);
-					measure.removeChild(note);
+					dealDotHalfNote(measure, divisions, note)
 				}
 			}
 		} 
 	}
+}
+
+/** 八几排的小节,二分休止符带附点 */
+const dealDotHalfNote = (measure: any, divisions: number, note: any) => {
+	// 如果音符带附点,需要判断处理下
+	if (note.getElementsByTagName("dot").length) {
+		const maxNumber = 2;
+		let quarterNoteNumber = 1;
+		while (quarterNoteNumber <= maxNumber) {
+			const newnote = document.createElement('note');
+			newnote.innerHTML = `
+			<rest></rest>
+			<duration>${divisions+divisions/2}</duration>
+			<voice>1</voice>
+			<type>quarter</type>
+			<dot></dot>`
+			measure.insertBefore(newnote, note);
+			quarterNoteNumber += 1;
+		};
+		measure.removeChild(note);
+	} else {
+		const newnote = document.createElement('note');
+		newnote.innerHTML = `
+		<rest></rest>
+		<duration>${divisions+divisions/2}</duration>
+		<voice>1</voice>
+		<type>quarter</type>
+		<dot></dot>`
+		measure.insertBefore(newnote, note);
+		const newnote2 = document.createElement('note');
+		newnote2.innerHTML = `
+		<rest></rest>
+		<duration>${divisions/2}</duration>
+		<voice>1</voice>
+		<type>eighth</type>`
+		measure.insertBefore(newnote2, note);
+		measure.removeChild(note);
+	}
 }

+ 6 - 3
src/helpers/formateMusic.ts

@@ -1569,16 +1569,19 @@ const customizationXml = (xmlParse: any) => {
 	const measures: any[] = Array.from(xmlParse.getElementsByTagName("measure"));
 	const notes: any[] = Array.from(xmlParse.getElementsByTagName("note"));
 
-	// 获取音符最多的歌词数,用于自定义循环播放次数
-	let maxLyricNum = 0;
+	// 获取音符最多的歌词数,time最多的次数,取两者的最大值,用于自定义循环播放次数
+	let maxLyricNum = 0, maxTimeNum = 0;
 	if (notes && notes.length) {
 		for (const note of notes) {
 			if (maxLyricNum < note.getElementsByTagName("lyric").length) {
 				maxLyricNum = note.getElementsByTagName("lyric").length
 			}
+			if (maxTimeNum < note.getElementsByTagName("time").length) {
+				maxTimeNum = note.getElementsByTagName("time").length
+			}
 		}
 	}
-	state.maxLyricNum = maxLyricNum;
+	state.maxLyricNum = Math.max(maxLyricNum, maxTimeNum);
 	// state.osmd.EngravingRules.DYCustomRepeatCount = maxLyricNum;
 	;(window as any).DYCustomRepeatCount = state.maxLyricNum;
 	console.log('歌词次数',maxLyricNum)