Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/hqyDev' into feature-tianyong

TIANYONG 7 mesi fa
parent
commit
176633677e
2 ha cambiato i file con 107 aggiunte e 126 eliminazioni
  1. 106 125
      src/helpers/metronome.ts
  2. 1 1
      src/view/audio-list/index.tsx

+ 106 - 125
src/helpers/metronome.ts

@@ -367,6 +367,7 @@ class Metronome {
 					const m = {
 						measureNumberXML: measureNumberXML,
 						measureNumberIndex: measureListIndex,
+						CompoundTempo: note?.noteElement?.sourceMeasure?.CompoundTempo || "",
 						numerator: note?.noteElement?.sourceMeasure?.ActiveTimeSignature?.numerator || 0,
 						start: startTime,
 						end: noteEndTime,
@@ -377,48 +378,15 @@ class Metronome {
 						svgs: [] as any[],
 						isRestFlag: note.isRestFlag,
 					};
-					// 2.统计小节的拍数
-					// 3.统计小节的时长, 开始时间,结束时间
-					// console.log(measureNumberXML,note.measures, times.filter((n: any) => n?.noteElement?.sourceMeasure?.measureListIndex == measureListIndex))
-					if ([121].includes(state.subjectId)) {
-						const _measures = times.filter((n: any) => n?.noteElement?.sourceMeasure?.measureListIndex == measureListIndex);
-						note.measures = _measures;
-						m.start = note.measures[0].time;
-						m.end = note.measures[note.measures.length - 1].endtime;
-						m.time = note.measures[note.measures.length - 1].endtime - note.measures[0].time;
-						try {
-							const tickables = note.noteElement.sourceMeasure.verticalMeasureList.reduce((arr: any[], value: any) => {
-								arr.push(...value.vfVoices["1"].tickables);
-								return arr;
-							}, []);
-							const xList: any[] = [];
-							m.svgs = tickables
-								.map((n: any) => {
-									const x = n.getBoundingBox().x;
-									if (!xList.includes(x) && n.duration !== "w") {
-										xList.push(x);
-										n._start_x = x;
-										return n;
-									}
-								})
-								.filter(Boolean)
-								.sort((a: any, b: any) => a._start_x - b._start_x);
-							// console.log(measureNumberXML, m.svgs)
-						} catch (error) {
-							console.log(error);
-						}
-						m.stepList = calculateMutilpleMetroStep(note.measures, m);
-					} else {
-						/**
-						 * bug:#9877
-						 * 多分轨合并显示,不同分轨的音符数量可能不同
-						 */
-						let measureArr = note.measures;
-						if (state.isCombineRender) {
-							measureArr = measureArr.filter((item: any) => item.MeasureNumberXML === m.measureNumberXML)
-						}
-						m.stepList = calculateMetroStep(measureArr, m);
+					/**
+					 * bug:#9877
+					 * 多分轨合并显示,不同分轨的音符数量可能不同
+					*/
+					let measureArr = note.measures;
+					if (state.isCombineRender) {
+						measureArr = measureArr.filter((item: any) => item.MeasureNumberXML === m.measureNumberXML)
 					}
+					m.stepList = calculateMetroStep(measureArr, m);
 					measures.push(m);
 					xmlNumber = measureNumberXML;
 				}
@@ -435,37 +403,58 @@ class Metronome {
 				measureNumberXML: item.measureNumberXML
 			}
 		}))
-		// 4.按照拍数将时长平均分配
 		try {
 			for (let i = 0; i < measures.length; i++) {
 				const measure = measures[i];
-				const noteStep = measure.time / measure.numerator;
-				// console.log("🚀 ~ measure.measureNumberXML",measure.measureNumberXML, noteStep)
-				const WIDTH = [121].includes(state.subjectId) ? 95 : 100;
-				const widthStep = WIDTH / (measure.numerator + 1);
+				// 87拍和45拍要根据小节返回的CompoundTempo特殊处理
+				const beatTypeArr = getBeatTypeArr(measure.CompoundTempo)
 				metroMeasure[i] = [] as number[];
-				// console.log('stepList', [...measure.stepList], measure.measureNumberXML)
-				for (let j = 0; j < measure.numerator; j++) {
-					const time = noteStep * j + measure.start;
+				for (let j = 0; j < beatTypeArr.length; j++) {
+					// 累加
+					const beatMuit = Array(j).fill("").reduce((num:number,v:any,i:number) => {
+						return num += Math.abs(beatTypeArr[i])
+					}, 0) || 0
+					const time = measure.time * beatMuit + measure.start;
 					metroList.push(time);
-					let left = "";
-					if (measure.stepList[j]) {
-						left = measure.stepList[j] + "px";
-					} else {
-						const preLeft = measure.stepList[j - 1];
-						left = !preLeft ? `${widthStep}%` : preLeft.toString().indexOf("%") > -1 ? `${preLeft} + ${widthStep}%` : `${preLeft}px + ${widthStep}%`;
-						measure.stepList[j] = left;
-					}
 					metroMeasure[i].push({
+						isTick: beatTypeArr[j] < 0,
 						index: j,
 						time,
-						// left: (measure.stepList[j] ? measure.stepList[j] + 'px' : (j + 1) * widthStep + '%'),
-						left: left?.indexOf("%") > -1 ? `calc(${left})` : left,
+						left: 0,
 						measureNumberXML: measure.measureNumberXML,
 						isRestFlag: measure.isRestFlag,
 					});
 				}
 			}
+			// for (let i = 0; i < measures.length; i++) {
+			// 	const measure = measures[i];
+			// 	const noteStep = measure.time / measure.numerator;
+			// 	// console.log("🚀 ~ measure.measureNumberXML",measure.measureNumberXML, noteStep)
+			// 	const WIDTH = 100;
+			// 	const widthStep = WIDTH / (measure.numerator + 1);
+			// 	metroMeasure[i] = [] as number[];
+			// 	// console.log('stepList', [...measure.stepList], measure.measureNumberXML)
+			// 	for (let j = 0; j < measure.numerator; j++) {
+			// 		const time = noteStep * j + measure.start;
+			// 		metroList.push(time);
+			// 		let left = "";
+			// 		if (measure.stepList[j]) {
+			// 			left = measure.stepList[j] + "px";
+			// 		} else {
+			// 			const preLeft = measure.stepList[j - 1];
+			// 			left = !preLeft ? `${widthStep}%` : preLeft.toString().indexOf("%") > -1 ? `${preLeft} + ${widthStep}%` : `${preLeft}px + ${widthStep}%`;
+			// 			measure.stepList[j] = left;
+			// 		}
+			// 		metroMeasure[i].push({
+			// 			index: j,
+			// 			time,
+			// 			// left: (measure.stepList[j] ? measure.stepList[j] + 'px' : (j + 1) * widthStep + '%'),
+			// 			left: left?.indexOf("%") > -1 ? `calc(${left})` : left,
+			// 			measureNumberXML: measure.measureNumberXML,
+			// 			isRestFlag: measure.isRestFlag,
+			// 		});
+			// 	}
+			// }
 		} catch (error) {
 			console.log(error);
 		}
@@ -478,6 +467,64 @@ class Metronome {
 	}
 }
 
+/** 获取节拍类型数组 */
+export function getBeatTypeArr(CompoundTempo?:string){
+	const speedBeatUnit = state.speedBeatUnit
+	const Numerator = state.osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4
+	const denominator = state.osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Denominator || 4
+	let loopArr = []
+	// 规则 负数代表重声,正数代表轻声
+	switch (`${Numerator}/${denominator}`) {
+		case "2/2":
+			loopArr = [-1/2, 1/2]
+			break;		
+		case "3/2":
+			loopArr = [-1/3, 1/3, 1/3]
+			break;
+		case "5/4":
+			//5/4拍根据谱面的CompoundTempo来特殊处理
+			if(CompoundTempo==="2+3"){
+				loopArr = [-1/5, 1/5, -1/5, 1/5, 1/5]
+			}else{
+				loopArr = [-1/5, 1/5, 1/5, -1/5, 1/5]
+			}
+			break;
+		case "3/8":
+			// 3/8拍 速度为浮点4分音符时候特殊处理
+			if(speedBeatUnit==="1/4."){
+				loopArr = [-1/1]
+			}else{
+				loopArr = [-1/3, 1/3, 1/3]
+			}
+			break;
+		case "6/8":
+			loopArr = [-1/2, 1/2]
+			break;	
+		case "7/8":
+			//7/8拍根据谱面的CompoundTempo来特殊处理
+			if(CompoundTempo==="2+2+3"){
+				loopArr = [-2/7, 2/7, 3/7]
+			}if(CompoundTempo==="2+3+2"){
+				loopArr = [-2/7, 3/7, 2/7]
+			}else{
+				loopArr = [-3/7, 2/7, 3/7]
+			}
+			break;	
+		case "9/8":
+			loopArr = [-3/9, 3/9, 3/9]
+				break;				
+		default:
+			loopArr.push(-1/Numerator);
+			for (let i = 1; i < Numerator; i++) {
+				loopArr.push(1/Numerator);
+			}
+			break;
+	}
+	console.log(loopArr, "loopArr")
+	return loopArr
+}
+
+
 // 计算拍子的时值
 function calculateMetroStep(arr: any[], m: any): number[] {
 	const measureLength = arr.reduce((total: number, item: any) => {
@@ -604,72 +651,6 @@ function calculateMetroStep(arr: any[], m: any): number[] {
 	// console.log("stepList", [...stepList], m.measureNumberXML);
 	return stepList;
 }
-// 计算单声部多声轨的拍子的时值
-function calculateMutilpleMetroStep(arr: any[], m: any): number[] {
-	// console.log("🚀 ~ m:", [...m.svgs])
-	const step = m.time / m.numerator;
-	const measure_bbox = arr[0]?.svgElement?.attrs?.el?.parentElement?.parentElement?.getBoundingClientRect?.() || { x: 0 };
-	if (arr.length === 1) {
-		const staveNote = m.svgs[0];
-		// 大于一拍
-		let bbox = staveNote?.attrs?.el?.getBoundingClientRect?.() || { x: 0 };
-		if (staveNote && !staveNote.isRest()) {
-			return [bbox.x - measure_bbox.x];
-		}
-		return [];
-	}
-	// console.log("🚀 ~ arr", arr, step, m.measureNumberXML);
-	let total = 0;
-	let notes: any[] = [];
-	let stepList: number[] = [];
-	for (let i = 0; i < arr.length; i++) {
-		const item = arr[i];
-		item._index = i;
-		const noteTime = item.endtime - item.time;
-		total += noteTime;
-		let svgEle = m.svgs[i]?.attrs?.el;
-		// 大于一拍
-		let bbox = svgEle?.getBoundingClientRect?.() || { x: 0 };
-		// console.log(m.measureNumberXML, svgEle, i)
-		if (noteTime > step) {
-			total -= step;
-			// console.log('超过一拍了', notes, m.measureNumberXML)
-			let x = bbox.x - measure_bbox.x;
-			if (notes.length > 0) {
-				svgEle = m.svgs[notes[0]._index]?.attrs?.el;
-				bbox = svgEle?.getBoundingClientRect?.() || { x: 0 };
-				x = bbox.x - measure_bbox.x;
-			}
-			stepList.push(x);
-			notes = [];
-		} else {
-			notes.push(item);
-		}
-		// console.log(notes)
-		if (Math.abs(total - step) < 0.001) {
-			let x = bbox.x - measure_bbox.x;
-			if (notes.length > 0) {
-				svgEle = m.svgs[notes[0]._index]?.attrs?.el;
-				bbox = svgEle?.getBoundingClientRect?.() || { x: 0 };
-				x = bbox.x - measure_bbox.x;
-			}
-			// console.log("一拍",svgEle,notes,m.svgs, m.measureNumberXML);
-			stepList.push(x);
-			total = 0;
-			notes = [];
-		}
-	}
-	stepList = stepList.reduce((list: any[], n: number) => {
-		if (list.includes(n)) {
-			list.push(undefined as any);
-		} else {
-			list.push(n);
-		}
-		return list;
-	}, []); //Array.from(new Set(stepList))
-	// console.log('stepList', stepList, m.measureNumberXML)
-	return stepList;
-}
 
 // 延迟兼容处理
 function setCurrentTime(time: number) {

+ 1 - 1
src/view/audio-list/index.tsx

@@ -359,7 +359,7 @@ export default defineComponent({
 				const beatsBgTime:number[] = []
 				metronomeData.metroMeasure.map(measures=>{
 					measures.map((item:any)=>{
-						beats.push(item.index===0?tickBuff!:tockBuff!)
+						beats.push(item.isTick?tickBuff!:tockBuff!)
 						beatsTime.push(item.time + silenceDuration) // xml 计算的时候 加上空白的时间
 						beatsBgTime.push(item.time + silenceBgDuration) // xml 计算的时候 加上空白的时间 没有背景不赋值
 					})