Explorar o código

节拍器 节奏 新规则

黄琪勇 hai 5 meses
pai
achega
568d3d78c2
Modificáronse 3 ficheiros con 100 adicións e 20 borrados
  1. 1 1
      osmd-extended
  2. 98 18
      src/helpers/metronome.ts
  3. 1 1
      src/view/audio-list/index.tsx

+ 1 - 1
osmd-extended

@@ -1 +1 @@
-Subproject commit dd68ffab2f3f6e194b3886981036f05dcd1de4ca
+Subproject commit 8a653186333a6f49d85b61d348e9009ba2803a07

+ 98 - 18
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,
@@ -402,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 = 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);
 		}
@@ -445,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) => {

+ 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 计算的时候 加上空白的时间 没有背景不赋值
 					})