123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /**
- * 曲谱节拍器
- * auth: lsq
- * time: 2022.11.14
- */
- import { reactive, watch } from "vue";
- import { Howl } from "howler";
- import tockAndTick from "/src/constant/tockAndTick.json";
- type IOptions = {
- speed: number;
- };
- export const metronomeData = reactive({
- disable: true,
- initPlayerState: false,
- lineShow: false,
- isClick: false,
- metro: null as unknown as Metronome,
- metroList: [] as number[],
- activeList: [] as number[],
- metroMeasure: [] as any[],
- activeIndex: null as unknown as number,
- activeMetro: {} as any,
- });
- class Metronome {
- playType = "tick";
- source = null as any; // 创建音频源头
- source1 = null as any;
- source2 = null as any;
- constructor(option?: IOptions) {}
- init(times: any[]) {
- this.calculation(times);
- metronomeData.activeList = [];
- }
- initPlayer() {
- if (!this.source) {
- this.source = this.loadAudio1();
- }
- this.source.volume(metronomeData.disable ? 0 : 1);
- // if (!this.source2) {
- // this.source2 = this.loadAudio2();
- // }
- metronomeData.initPlayerState = true;
- }
- // 播放
- sound = (currentTime: number) => {
- let index = -1;
- let activeMetro = -1;
- for (let i = 0; i < metronomeData.metroList.length; i++) {
- const item = metronomeData.metroList[i];
- if (currentTime >= item) {
- // console.log(currentTime , item)
- index = i;
- activeMetro = item;
- } else {
- break;
- }
- }
- if (index > -1 && metronomeData.activeIndex !== index) {
- metronomeData.activeIndex = index;
- // console.log("播放", index);
- // metronomeData.activeMetro = this.getStep(activeMetro);
- // console.log("🚀 ~ metronomeData.activeMetro",metronomeData.activeMetro.measureNumberIndex, metronomeData.activeMetro.index)
- this.playAudio();
- return;
- }
- };
- // 播放
- playAudio = () => {
- if (!metronomeData.initPlayerState) return;
- this.source.play();
- };
- // 切换
- selectPlay() {}
- loadAudio1 = () => {
- return new Howl({
- src: tockAndTick.tick,
- });
- };
- loadAudio2 = () => {
- return new Howl({
- src: tockAndTick.tock,
- });
- };
- getStep(time: number) {
- for (let i = 0; i < metronomeData.metroMeasure.length; i++) {
- const list = metronomeData.metroMeasure[i];
- const item = list.find((n: any) => n.time === time);
- if (item) {
- // console.log('index',item)
- return item;
- }
- }
- return {};
- }
- // 计算 所有的拍子的时间
- calculation(times: any[]) {
- // console.log("🚀 ~ times", times);
- // 1.统计有多少小节
- 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 , xmlNumber)
- // console.log("🚀 ~ measureNumberXML", note)
- if (measureNumberXML > -1) {
- if (measureNumberXML != measureListIndex) {
- const m = {
- measureNumberXML: measureNumberXML,
- numerator: note?.measure?.numerator || 0,
- time: note?.timeNote?.millisecondsPerMeasure,
- stepList: [] as number[],
- notes: [note] as any[],
- };
- xmlNumber++;
- measures[xmlNumber] = m;
- measureListIndex = measureNumberXML;
- } else {
- measures[xmlNumber].notes.push(note);
- }
- }
- }
- // 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 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);
- }
- }
- } catch (error) {
- console.log(error);
- }
- // console.log(metroList, metroList.length);
- // 5.得到所有的节拍时间
- metronomeData.metroList = metroList;
- metronomeData.metroMeasure = metroMeasure;
- metronomeData.activeMetro = metroMeasure[0]?.[0] || {};
- }
- }
- export default Metronome;
|