|
@@ -35,12 +35,13 @@ class Metronome {
|
|
|
metronomeData.activeList = [];
|
|
|
}
|
|
|
initPlayer() {
|
|
|
- if (!this.source1) {
|
|
|
- this.source1 = this.loadAudio1();
|
|
|
- }
|
|
|
- if (!this.source2) {
|
|
|
- this.source2 = this.loadAudio2();
|
|
|
+ if (!this.source) {
|
|
|
+ this.source = this.loadAudio1();
|
|
|
}
|
|
|
+ this.source.volume(metronomeData.disable ? 0 : 1);
|
|
|
+ // if (!this.source2) {
|
|
|
+ // this.source2 = this.loadAudio2();
|
|
|
+ // }
|
|
|
metronomeData.initPlayerState = true;
|
|
|
}
|
|
|
|
|
@@ -61,20 +62,16 @@ class Metronome {
|
|
|
}
|
|
|
if (index > -1 && metronomeData.activeIndex !== index) {
|
|
|
metronomeData.activeIndex = index;
|
|
|
- // console.log("播放", metronomeData.activeIndex);
|
|
|
- metronomeData.activeMetro = this.getStep(activeMetro);
|
|
|
+ // console.log("播放", index);
|
|
|
+ // metronomeData.activeMetro = this.getStep(activeMetro);
|
|
|
// console.log("🚀 ~ metronomeData.activeMetro",metronomeData.activeMetro.measureNumberIndex, metronomeData.activeMetro.index)
|
|
|
this.playAudio();
|
|
|
- metronomeData.isClick = false;
|
|
|
return;
|
|
|
}
|
|
|
- metronomeData.isClick = false;
|
|
|
};
|
|
|
// 播放
|
|
|
playAudio = () => {
|
|
|
if (!metronomeData.initPlayerState) return;
|
|
|
- this.source = metronomeData.activeMetro?.index === 0 ? this.source1 : this.source2;
|
|
|
- this.source.volume(metronomeData.disable ? 0 : 1);
|
|
|
this.source.play();
|
|
|
};
|
|
|
|
|
@@ -107,76 +104,57 @@ class Metronome {
|
|
|
calculation(times: any[]) {
|
|
|
// console.log("🚀 ~ times", times);
|
|
|
// 1.统计有多少小节
|
|
|
- const measures: any = {};
|
|
|
+ const measures: any[] = [];
|
|
|
let xmlNumber = -1;
|
|
|
+ let measureListIndex = -1;
|
|
|
for (let i = 0; i < times.length; i++) {
|
|
|
const note = times[i];
|
|
|
const measureNumberXML = note?.timeNote?.measureNumber;
|
|
|
// console.log("🚀 ~ note?.noteElement?.sourceMeasure", note?.noteElement?.sourceMeasure)
|
|
|
- // console.log("🚀 ~ measureNumberXML", measureNumberXML, note)
|
|
|
+ // console.log("🚀 ~ measureNumberXML", measureNumberXML , xmlNumber)
|
|
|
// console.log("🚀 ~ measureNumberXML", note)
|
|
|
if (measureNumberXML > -1) {
|
|
|
- if (measureNumberXML != xmlNumber) {
|
|
|
+ if (measureNumberXML != measureListIndex) {
|
|
|
const m = {
|
|
|
measureNumberXML: measureNumberXML,
|
|
|
numerator: note?.measure?.numerator || 0,
|
|
|
time: note?.timeNote?.millisecondsPerMeasure,
|
|
|
stepList: [] as number[],
|
|
|
- isRestFlag: note.isRestFlag,
|
|
|
- notes: [] as any[]
|
|
|
+ notes: [note] as any[],
|
|
|
};
|
|
|
- measures[measureNumberXML] = m;
|
|
|
- xmlNumber = measureNumberXML;
|
|
|
+ xmlNumber++;
|
|
|
+ measures[xmlNumber] = m;
|
|
|
+ measureListIndex = measureNumberXML;
|
|
|
} else {
|
|
|
- measures[measureNumberXML].notes.push(note);
|
|
|
+ measures[xmlNumber].notes.push(note);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- console.log(measures, measures.length);
|
|
|
- return
|
|
|
-
|
|
|
- // 2.统计小节的拍数
|
|
|
- // 3.统计小节的时长, 开始时间,结束时间
|
|
|
- // console.log(measureNumberXML,note.measures, times.filter((n: any) => n?.noteElement?.sourceMeasure?.measureListIndex == measureListIndex))
|
|
|
- // m.stepList = calculateMetroStep(note.measures, m);
|
|
|
-
|
|
|
- let metroList: number[] = [];
|
|
|
+ // console.log(measures, measures.length);
|
|
|
+ const metroList: number[] = [];
|
|
|
const metroMeasure: any[] = [];
|
|
|
// 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);
|
|
|
- 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;
|
|
|
+ const calp = 1 / measure.numerator;
|
|
|
+ // console.log("🚀 ~ measure.numerator:", measure.numerator)
|
|
|
+ const totalMeasureTime = measure.notes.reduce((total: number, note: any) => {
|
|
|
+ return total + note?.abcNote?.duration;
|
|
|
+ }, 0);
|
|
|
+ const step = Math.floor(totalMeasureTime / calp);
|
|
|
+ // console.log('🚀 ~ calp:', calp, 'total', totalMeasureTime, 'step', step)
|
|
|
+ const startTime = measure.notes[0].timeNote.milliseconds;
|
|
|
+ const stepTime = measure.notes[0].timeNote.millisecondsPerMeasure / measure.numerator;
|
|
|
+ for (let j = 0; j < step; j++) {
|
|
|
+ const time = stepTime * j + startTime;
|
|
|
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);
|
|
|
}
|
|
|
- // console.log(metroList, metroMeasure);
|
|
|
+ // console.log(metroList, metroList.length);
|
|
|
// 5.得到所有的节拍时间
|
|
|
metronomeData.metroList = metroList;
|
|
|
metronomeData.metroMeasure = metroMeasure;
|
|
@@ -184,112 +162,4 @@ class Metronome {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 计算拍子的时值
|
|
|
-function calculateMetroStep(arr: any[], m: any): number[] {
|
|
|
- const measureLength = arr.reduce((total: number, item: any) => {
|
|
|
- total += item._noteLength;
|
|
|
- return total;
|
|
|
- }, 0);
|
|
|
- const clap = measureLength / m.numerator;
|
|
|
- if (arr.length === 1) {
|
|
|
- const wholeNote = arr[0].svgElement;
|
|
|
- if (wholeNote && !wholeNote.isRest()) {
|
|
|
- const measure_bbox = wholeNote?.attrs?.el?.parentElement?.parentElement?.getBoundingClientRect?.() || { x: 0, right: 0 };
|
|
|
- let bbox = wholeNote?.attrs?.el?.getBoundingClientRect?.() || { x: 0 };
|
|
|
- let stepWidth = Math.abs(measure_bbox.right - bbox.x) / m.numerator;
|
|
|
- let stepList: number[] = [];
|
|
|
- for (let i = 0; i < m.numerator; i++) {
|
|
|
- stepList.push(bbox.x - measure_bbox.x + i * stepWidth);
|
|
|
- }
|
|
|
- // console.log("🚀 ~ stepList:", stepList, m.measureNumberXML)
|
|
|
- return stepList;
|
|
|
- }
|
|
|
- try {
|
|
|
- // 开头是休止符
|
|
|
- if (m.measureNumberXML === 1 && wholeNote && wholeNote.isRest()) {
|
|
|
- const measure_bbox = wholeNote?.attrs?.el?.parentElement?.parentElement?.getBoundingClientRect?.() || { x: 0, right: 0 };
|
|
|
- let bbox = wholeNote?.attrs?.el?.getBoundingClientRect?.() || { x: 0 };
|
|
|
- let stepWidth = Math.abs(measure_bbox.right - bbox.x) / m.numerator;
|
|
|
- let stepList: number[] = [];
|
|
|
- for (let i = -1; i < m.numerator - 1; i++) {
|
|
|
- stepList.push(bbox.x - measure_bbox.x + i * stepWidth);
|
|
|
- }
|
|
|
- // console.log(wholeNote?.attrs?.el, m.measureNumberXML)
|
|
|
- // console.log("🚀 ~ stepList:", stepList, m.measureNumberXML)
|
|
|
- return stepList;
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.log("🚀 ~ error:", error);
|
|
|
- }
|
|
|
-
|
|
|
- return [];
|
|
|
- }
|
|
|
- // console.log("🚀 ~ arr", [...arr],`小节总时值: ${measureLength}`, clap, m.measureNumberXML);
|
|
|
- let totalLength = 0;
|
|
|
- let notes: any[] = [];
|
|
|
- let stepList: number[] = [];
|
|
|
- for (let i = 0; i < arr.length; i++) {
|
|
|
- const item = arr[i];
|
|
|
- item.index = i;
|
|
|
- const noteLength = item._noteLength;
|
|
|
- totalLength += noteLength;
|
|
|
- // 大于一拍
|
|
|
- const exceedStep = Math.floor(totalLength / clap);
|
|
|
- // console.log(`note`, item?.svgElement?.attrs?.el,notes.length,{noteLength, exceedStep,clap}, m.measureNumberXML)
|
|
|
- if (exceedStep >= 1) {
|
|
|
- totalLength -= clap;
|
|
|
- // 一拍
|
|
|
- const measure_bbox = item?.svgElement?.attrs?.el?.parentElement?.parentElement?.getBoundingClientRect?.() || { x: 0 };
|
|
|
- if (notes.length > 0) {
|
|
|
- let bbox = notes[0]?.svgElement?.attrs?.el?.getBoundingClientRect?.() || { x: 0 };
|
|
|
- let x: any = bbox.x - measure_bbox.x;
|
|
|
- if (notes[0]._noteLength / clap >= 1) {
|
|
|
- const nextNote = arr[notes[0].index + 1]?.svgElement?.attrs?.el?.getBoundingClientRect?.() || { x: measure_bbox.right } || { x: 0 };
|
|
|
- const stepWidth = Math.abs(bbox.x - nextNote.x) / 2;
|
|
|
- x = bbox.x - measure_bbox.x + stepWidth;
|
|
|
- // console.log(`音符超一拍`, notes[0]?.svgElement?.attrs?.el, arr[notes[0].index + 1]?.svgElement?.attrs?.el, bbox.x - nextNote.x, stepWidth, m.measureNumberXML);
|
|
|
- }
|
|
|
- // console.log(`一拍`, notes[0]?.svgElement?.attrs?.el, m.measureNumberXML, notes[0]._noteLength , clap, 'aa')
|
|
|
- stepList.push(x);
|
|
|
- } else {
|
|
|
- let bbox = item?.svgElement?.attrs?.el?.getBoundingClientRect?.() || { x: 0 };
|
|
|
- let x: any = bbox.x - measure_bbox.x;
|
|
|
- // console.log(`一拍`, item?.svgElement?.attrs?.el, m.measureNumberXML)
|
|
|
- stepList.push(x);
|
|
|
- }
|
|
|
- notes = [];
|
|
|
- let bbox = item?.svgElement?.attrs?.el?.getBoundingClientRect?.() || { x: 0 };
|
|
|
- let x: any = bbox.x - measure_bbox.x;
|
|
|
- let stepWidth = 0;
|
|
|
- if (exceedStep > 1) {
|
|
|
- // 二拍以上
|
|
|
- const nextNote = arr[i + 1]?.svgElement?.attrs?.el?.getBoundingClientRect?.() || { x: measure_bbox.right } || { x: 0 };
|
|
|
- stepWidth = Math.abs(bbox.x - nextNote.x) / exceedStep;
|
|
|
- // console.log("二拍以上 ~ nextNote:",bbox.x , nextNote.x,stepWidth, item?.svgElement?.attrs?.el,arr[i + 1]?.svgElement?.attrs?.el, exceedStep);
|
|
|
- }
|
|
|
-
|
|
|
- for (let j = 1; j < exceedStep; j++) {
|
|
|
- totalLength -= clap;
|
|
|
- // console.log(`超一拍`,item?.svgElement?.attrs?.el, m.measureNumberXML)
|
|
|
- stepList.push(x + stepWidth * j);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //有时值就将音符加入
|
|
|
- if (totalLength > Number.EPSILON && totalLength > 0) {
|
|
|
- notes.push(item);
|
|
|
- }
|
|
|
- }
|
|
|
- stepList = stepList.reduce((list: any[], n: number) => {
|
|
|
- if (list.includes(n)) {
|
|
|
- list.push(undefined as any);
|
|
|
- } else {
|
|
|
- list.push(n);
|
|
|
- }
|
|
|
- return list;
|
|
|
- }, []);
|
|
|
- // console.log("stepList", [...stepList], m.measureNumberXML);
|
|
|
- return stepList;
|
|
|
-}
|
|
|
-
|
|
|
export default Metronome;
|