|
@@ -8,10 +8,10 @@ import { IFingering, mappingVoicePart, subjectFingering, matchVoicePart } from "
|
|
import { handleStartTick, closeTick } from "./view/tick";
|
|
import { handleStartTick, closeTick } from "./view/tick";
|
|
import { audioListStart, getAudioCurrentTime, getAudioDuration, setAudioCurrentTime, setAudioPlaybackRate, audioData } from "./view/audio-list";
|
|
import { audioListStart, getAudioCurrentTime, getAudioDuration, setAudioCurrentTime, setAudioPlaybackRate, audioData } from "./view/audio-list";
|
|
import { toggleFollow } from "./view/follow-practice";
|
|
import { toggleFollow } from "./view/follow-practice";
|
|
-import { browser, setStorageSpeed, setGlobalData } from "./utils";
|
|
|
|
|
|
+import { browser, setStorageSpeed, setGlobalData, checkDecimal } from "./utils";
|
|
import { api_cloudGetMediaStatus, api_createMusicPlayer, api_cloudChangeSpeed, api_cloudSuspend, api_cloudSetCurrentTime, api_cloudDestroy } from "./helpers/communication";
|
|
import { api_cloudGetMediaStatus, api_createMusicPlayer, api_cloudChangeSpeed, api_cloudSuspend, api_cloudSetCurrentTime, api_cloudDestroy } from "./helpers/communication";
|
|
import { verifyCanRepeat, getDuration, xmlAddPartName } from "./helpers/formateMusic";
|
|
import { verifyCanRepeat, getDuration, xmlAddPartName } from "./helpers/formateMusic";
|
|
-import { getMusicSheetDetail } from "./utils/baseApi"
|
|
|
|
|
|
+import { getMusicSheetDetail, getInstrumentCode } from "./utils/baseApi"
|
|
import { getQuery } from "/src/utils/queryString";
|
|
import { getQuery } from "/src/utils/queryString";
|
|
import { followData, skipNotePractice } from "/src/view/follow-practice/index"
|
|
import { followData, skipNotePractice } from "/src/view/follow-practice/index"
|
|
import { changeSongSourceByBeat } from "/src/view/audio-list"
|
|
import { changeSongSourceByBeat } from "/src/view/audio-list"
|
|
@@ -25,6 +25,8 @@ import { undoData, moveData } from "/src/view/plugins/move-music-score"
|
|
import { HANDLE_WORK_ADD } from "/src/page-instrument/custom-plugins/work-index";
|
|
import { HANDLE_WORK_ADD } from "/src/page-instrument/custom-plugins/work-index";
|
|
import { speedBeatTo, unitImgs } from "/src/helpers/beatConfig"
|
|
import { speedBeatTo, unitImgs } from "/src/helpers/beatConfig"
|
|
import IndexedDBService from "/src/utils/indexedDB";
|
|
import IndexedDBService from "/src/utils/indexedDB";
|
|
|
|
+import { musicalInstrumentCodeInfo, instruments, fixInstrumentNameCode } from "/src/constant/instruments";
|
|
|
|
+import evaluatModel from "./page-instrument/evaluat-model";
|
|
|
|
|
|
const query: any = getQuery();
|
|
const query: any = getQuery();
|
|
|
|
|
|
@@ -61,229 +63,6 @@ export type ISonges = {
|
|
*/
|
|
*/
|
|
const classids = [1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 30, 31, 35, 36, 38, 108, 150, 151, 152, 153, 154, 155, 156, 157, 158, 178, 179, 180, 181, 182]; // 大雅金唐, 竖笛教程, 声部训练展开的分类ID
|
|
const classids = [1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 30, 31, 35, 36, 38, 108, 150, 151, 152, 153, 154, 155, 156, 157, 158, 178, 179, 180, 181, 182]; // 大雅金唐, 竖笛教程, 声部训练展开的分类ID
|
|
|
|
|
|
-// 乐器code码
|
|
|
|
-export const musicalInstrumentCodeInfo = [
|
|
|
|
- {
|
|
|
|
- name: '长笛',
|
|
|
|
- code: 'Flute',
|
|
|
|
- id: 1
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '短笛',
|
|
|
|
- code: 'Piccolo',
|
|
|
|
- id: 2
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '单簧管',
|
|
|
|
- code: 'Clarinet',
|
|
|
|
- id: 3
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '低音单簧管',
|
|
|
|
- code: 'Bass Clarinet',
|
|
|
|
- id: 4
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '中音萨克斯',
|
|
|
|
- code: 'Alto Saxophone',
|
|
|
|
- id: 5
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '次中音萨克斯',
|
|
|
|
- code: 'Tenor Saxophone',
|
|
|
|
- id: 6
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '高音萨克斯',
|
|
|
|
- code: 'Soprano Saxophone',
|
|
|
|
- id: 7
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '上低音萨克斯',
|
|
|
|
- code: 'Baritone Saxophone',
|
|
|
|
- id: 8
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '双簧管',
|
|
|
|
- code: 'Oboe',
|
|
|
|
- id: 9
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '大管',
|
|
|
|
- code: 'Bassoon',
|
|
|
|
- id: 10
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '小号',
|
|
|
|
- code: 'Trumpet',
|
|
|
|
- id: 11
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '圆号',
|
|
|
|
- code: 'Horn',
|
|
|
|
- id: 12
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '长号',
|
|
|
|
- code: 'Trombone',
|
|
|
|
- id: 13
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '上低音号',
|
|
|
|
- code: 'Baritone',
|
|
|
|
- id: 14
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '次中音号',
|
|
|
|
- code: 'Euphonium',
|
|
|
|
- id: 15
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '大号',
|
|
|
|
- code: 'Tuba',
|
|
|
|
- id: 16
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '钢琴',
|
|
|
|
- code: 'Piano',
|
|
|
|
- id: 17
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '电钢琴',
|
|
|
|
- code: 'Electronical Piano',
|
|
|
|
- id: 18
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '钢片琴',
|
|
|
|
- code: 'Glockenspiel',
|
|
|
|
- id: 19
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '小提琴',
|
|
|
|
- code: 'Violin',
|
|
|
|
- id: 20
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '中提琴',
|
|
|
|
- code: 'Viola',
|
|
|
|
- id: 21
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '大提琴',
|
|
|
|
- code: 'Violoncello',
|
|
|
|
- id: 22
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '低音提琴',
|
|
|
|
- code: 'Contrabass',
|
|
|
|
- id: 23
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '架子鼓',
|
|
|
|
- code: 'Drum Set',
|
|
|
|
- id: 24
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '小鼓',
|
|
|
|
- code: 'Snare Drum',
|
|
|
|
- id: 25
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '马林巴',
|
|
|
|
- code: 'Marimba',
|
|
|
|
- id: 26
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '颤音琴',
|
|
|
|
- code: 'Vibraphone',
|
|
|
|
- id: 27
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '钟琴',
|
|
|
|
- code: 'Chimes',
|
|
|
|
- id: 28
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '木琴',
|
|
|
|
- code: 'Xylophone',
|
|
|
|
- id: 29
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '管钟',
|
|
|
|
- code: 'Tubular Bells',
|
|
|
|
- id: 30
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '定音鼓',
|
|
|
|
- code: 'Timpani',
|
|
|
|
- id: 31
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '键盘',
|
|
|
|
- code: 'Mallets',
|
|
|
|
- id: 32
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '排箫',
|
|
|
|
- code: 'Panpipes',
|
|
|
|
- id: 33
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '陶笛',
|
|
|
|
- code: 'Ocarina',
|
|
|
|
- id: 34
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '陶笛',
|
|
|
|
- code: 'Alto Ocarina',
|
|
|
|
- id: 34
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '葫芦丝',
|
|
|
|
- code: 'Woodwind',
|
|
|
|
- id: 35
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '葫芦丝',
|
|
|
|
- code: 'Hulusi',
|
|
|
|
- id: 35
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '口风琴',
|
|
|
|
- code: 'Nai',
|
|
|
|
- id: 36
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '口风琴',
|
|
|
|
- code: 'Melodica',
|
|
|
|
- id: 36
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '德式竖笛',
|
|
|
|
- code: 'Tenor Recorder',
|
|
|
|
- id: 37
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '德式竖笛',
|
|
|
|
- code: 'German Recorder',
|
|
|
|
- id: 37
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '英式竖笛',
|
|
|
|
- code: 'Baroque Recorder',
|
|
|
|
- id: 38
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '高音陶笛',
|
|
|
|
- code: 'Whistling',
|
|
|
|
- id: 39
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: '高音陶笛',
|
|
|
|
- code: 'Soprano Ocarina',
|
|
|
|
- id: 39
|
|
|
|
- },
|
|
|
|
-]
|
|
|
|
|
|
|
|
const state = reactive({
|
|
const state = reactive({
|
|
systemType: "" as "teacher" | "web" | "student",
|
|
systemType: "" as "teacher" | "web" | "student",
|
|
@@ -571,7 +350,7 @@ const state = reactive({
|
|
// 加载条
|
|
// 加载条
|
|
isLoading: true,
|
|
isLoading: true,
|
|
/** 加载中的文案 */
|
|
/** 加载中的文案 */
|
|
- loadingText: '音频资源加载中,请稍后…',
|
|
|
|
|
|
+ loadingText: '资源加载中,请稍后…',
|
|
/** 是否是简单的单行谱模式页面 */
|
|
/** 是否是简单的单行谱模式页面 */
|
|
isSimplePage: false,
|
|
isSimplePage: false,
|
|
/** xml的速度和后台设置的速度,计算出的基础音频播放倍率 */
|
|
/** xml的速度和后台设置的速度,计算出的基础音频播放倍率 */
|
|
@@ -611,6 +390,10 @@ const state = reactive({
|
|
isSingleMutliTrack: false,
|
|
isSingleMutliTrack: false,
|
|
/** 是否是来源于缓存的xml */
|
|
/** 是否是来源于缓存的xml */
|
|
xmlFromStore: false,
|
|
xmlFromStore: false,
|
|
|
|
+ /** 是否已经初始化评测音频,只有切了声轨后,才需要重新传音频,普通的切谱面(五线谱、简谱;单行谱、多行谱等)不需要重复传 */
|
|
|
|
+ evaluatAudioInitDone: false,
|
|
|
|
+ /** 是否使用原生评测服务 */
|
|
|
|
+ useNativeEvaluation: false,
|
|
});
|
|
});
|
|
const browserInfo = browser();
|
|
const browserInfo = browser();
|
|
let offset_duration = 0;
|
|
let offset_duration = 0;
|
|
@@ -750,7 +533,14 @@ const handlePlaying = () => {
|
|
// 如果开启了预备拍
|
|
// 如果开启了预备拍
|
|
const selectStartItem = state.sectionFirst ? state.sectionFirst : state.section[0];
|
|
const selectStartItem = state.sectionFirst ? state.sectionFirst : state.section[0];
|
|
const selectEndItem = state.section[1];
|
|
const selectEndItem = state.section[1];
|
|
- if (currentTime - selectEndItem.endtime >= 0) {
|
|
|
|
|
|
+ // 如果选段播放结束,或者音频播放结束(判断条件:currentTime >= duration)
|
|
|
|
+ // console.log('时间',currentTime,duration)
|
|
|
|
+ /**
|
|
|
|
+ * TODO:兼容音频时长比xml时值短的曲子
|
|
|
|
+ * isAudioShort:音频比选段的xml时值短,部分手机最后一帧返回的currentTime会比duration小,在这里加上一帧的时间(0.1666~0.2)
|
|
|
|
+ */
|
|
|
|
+ const isAudioShort = duration < selectEndItem.endtime
|
|
|
|
+ if ( (currentTime - selectEndItem.endtime >= 0) || (isAudioShort && (currentTime+0.02 >= duration)) ) {
|
|
console.log("选段播放结束", state.setting.repeatAutoPlay);
|
|
console.log("选段播放结束", state.setting.repeatAutoPlay);
|
|
// 如果为选段评测模式
|
|
// 如果为选段评测模式
|
|
if (state.modeType === "evaluating" && state.isSelectMeasureMode) {
|
|
if (state.modeType === "evaluating" && state.isSelectMeasureMode) {
|
|
@@ -838,6 +628,10 @@ export const skipNotePlay = async (itemIndex: number, isStart = false, handType?
|
|
if (item.measureSpeed && state.section.length < 2) {
|
|
if (item.measureSpeed && state.section.length < 2) {
|
|
// console.log('速度3')
|
|
// console.log('速度3')
|
|
state.speed = state.basePlayRate * 10000 * item.measureSpeed / 10000
|
|
state.speed = state.basePlayRate * 10000 * item.measureSpeed / 10000
|
|
|
|
+ // 如果是接近整数的小数,则取整
|
|
|
|
+ if ( checkDecimal(state.speed) ) {
|
|
|
|
+ state.speed = Math.round(state.speed)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
setAudioCurrentTime(itemTime, itemIndex);
|
|
setAudioCurrentTime(itemTime, itemIndex);
|
|
// 一行谱,点击音符,或者播放完成,需要跳转音符位置
|
|
// 一行谱,点击音符,或者播放完成,需要跳转音符位置
|
|
@@ -867,7 +661,7 @@ export const skipNotePlay = async (itemIndex: number, isStart = false, handType?
|
|
export const togglePlay = async (playState: "play" | "paused", isForceCLoseToast?:boolean) => {
|
|
export const togglePlay = async (playState: "play" | "paused", isForceCLoseToast?:boolean) => {
|
|
// 如果mp3资源还在加载中,给出提示
|
|
// 如果mp3资源还在加载中,给出提示
|
|
if (!state.isAppPlay && !state.audioDone) {
|
|
if (!state.isAppPlay && !state.audioDone) {
|
|
- if (!isForceCLoseToast) showToast('音频资源加载中,请稍后')
|
|
|
|
|
|
+ if (!isForceCLoseToast) showToast('资源加载中,请稍后...')
|
|
return
|
|
return
|
|
}
|
|
}
|
|
// 播放之前 当为评测模式和不为MIDI时候按 是否禁用节拍器 切换音源
|
|
// 播放之前 当为评测模式和不为MIDI时候按 是否禁用节拍器 切换音源
|
|
@@ -1408,17 +1202,18 @@ export const scrollViewNote = (resetTop?: boolean) => {
|
|
if (offsetTop === cursorElement.offsetTop || Math.abs(offsetTop - cursorElement.offsetTop) < 30) return;
|
|
if (offsetTop === cursorElement.offsetTop || Math.abs(offsetTop - cursorElement.offsetTop) < 30) return;
|
|
}
|
|
}
|
|
offsetTop = cursorElement.offsetTop;
|
|
offsetTop = cursorElement.offsetTop;
|
|
|
|
+ const animateType = browser().android ? "instant" : "smooth"
|
|
if (offsetTop > (state.headTopHeight + 30)) {
|
|
if (offsetTop > (state.headTopHeight + 30)) {
|
|
musicScrollTop = (offsetTop - state.headTopHeight - 30) * state.musicZoom
|
|
musicScrollTop = (offsetTop - state.headTopHeight - 30) * state.musicZoom
|
|
musicAndSelection.scrollTo({
|
|
musicAndSelection.scrollTo({
|
|
top: (offsetTop - state.headTopHeight - 30) * state.musicZoom,
|
|
top: (offsetTop - state.headTopHeight - 30) * state.musicZoom,
|
|
- behavior: "auto",
|
|
|
|
|
|
+ behavior: animateType,
|
|
});
|
|
});
|
|
} else {
|
|
} else {
|
|
musicScrollTop = 0
|
|
musicScrollTop = 0
|
|
musicAndSelection.scrollTo({
|
|
musicAndSelection.scrollTo({
|
|
top: 0,
|
|
top: 0,
|
|
- behavior: "auto",
|
|
|
|
|
|
+ behavior: animateType,
|
|
});
|
|
});
|
|
}
|
|
}
|
|
};
|
|
};
|
|
@@ -1451,12 +1246,17 @@ export default state;
|
|
|
|
|
|
/** 初始化评测音频 */
|
|
/** 初始化评测音频 */
|
|
export const evaluatCreateMusicPlayer = () => {
|
|
export const evaluatCreateMusicPlayer = () => {
|
|
- return api_createMusicPlayer({
|
|
|
|
|
|
+ if (state.evaluatAudioInitDone) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ api_createMusicPlayer({
|
|
musicSrc: state.accompany || state.music, // 曲谱音频url
|
|
musicSrc: state.accompany || state.music, // 曲谱音频url
|
|
// tuneSrc: "https://oss.dayaedu.com/cloud-coach/1686725501654check_music1_(1).mp3", //效音音频url
|
|
// tuneSrc: "https://oss.dayaedu.com/cloud-coach/1686725501654check_music1_(1).mp3", //效音音频url
|
|
tuneSrc: "https://oss.dayaedu.com/MECMP/1722593665681.mp3", //效音音频url
|
|
tuneSrc: "https://oss.dayaedu.com/MECMP/1722593665681.mp3", //效音音频url
|
|
checkFrequence: 496,
|
|
checkFrequence: 496,
|
|
|
|
+ useNativeEvaluation: state.useNativeEvaluation // 是否使用原生评测服务
|
|
});
|
|
});
|
|
|
|
+ state.evaluatAudioInitDone = true
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -1469,6 +1269,19 @@ export const getMusicDetail = async (id: string, type?: string) => {
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+// 获取后台配置的声轨编码
|
|
|
|
+const initInstrumentCode = async () => {
|
|
|
|
+ const res = await getInstrumentCode();
|
|
|
|
+ if (res?.code === 200 && res.data?.length) {
|
|
|
|
+ for (let item of res.data) {
|
|
|
|
+ const codes = item.code.split(',') || [item.code]
|
|
|
|
+ codes.forEach((code: any) => {
|
|
|
|
+ instruments[code] = item.name
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // console.log('声轨codes',instruments)
|
|
|
|
+}
|
|
|
|
|
|
// 判断有没有xml缓存,有则直接使用
|
|
// 判断有没有xml缓存,有则直接使用
|
|
const queryMusicXml = async (id: string, xmlUr: string) => {
|
|
const queryMusicXml = async (id: string, xmlUr: string) => {
|
|
@@ -1490,6 +1303,11 @@ const queryMusicXml = async (id: string, xmlUr: string) => {
|
|
}
|
|
}
|
|
|
|
|
|
const getMusicInfo = async (res: any) => {
|
|
const getMusicInfo = async (res: any) => {
|
|
|
|
+ try {
|
|
|
|
+ await initInstrumentCode()
|
|
|
|
+ } catch (error) {
|
|
|
|
+ // console.log(error)
|
|
|
|
+ }
|
|
// 是否支持总谱
|
|
// 是否支持总谱
|
|
state.isScoreRender = res.data?.isScoreRender
|
|
state.isScoreRender = res.data?.isScoreRender
|
|
// 是否默认显示总谱
|
|
// 是否默认显示总谱
|
|
@@ -1501,7 +1319,7 @@ const getMusicInfo = async (res: any) => {
|
|
/* 获取声轨列表 */
|
|
/* 获取声轨列表 */
|
|
const tracks = xmlToTracks(xmlString)
|
|
const tracks = xmlToTracks(xmlString)
|
|
// 是否显示节拍器 (管乐迷 默认显示节拍器)
|
|
// 是否显示节拍器 (管乐迷 默认显示节拍器)
|
|
- //state.isMixBeat = res.data?.isMixBeat
|
|
|
|
|
|
+ state.isMixBeat = res.data?.isMixBeat
|
|
/* 设置partIndex */
|
|
/* 设置partIndex */
|
|
let partIndexs = query["part-index"] ? query["part-index"].split(",") : ["-1"] // -1为partIndex没有值的时候
|
|
let partIndexs = query["part-index"] ? query["part-index"].split(",") : ["-1"] // -1为partIndex没有值的时候
|
|
// 如果传入的是part-name,需要将part-name转换成part-index
|
|
// 如果传入的是part-name,需要将part-name转换成part-index
|
|
@@ -1535,21 +1353,29 @@ const getMusicInfo = async (res: any) => {
|
|
} else {
|
|
} else {
|
|
(window as any).DYFirstTrackName = '';
|
|
(window as any).DYFirstTrackName = '';
|
|
}
|
|
}
|
|
- // 如果是作业模式,需要默认渲染当前学生声部对应的声轨,并且默认不显示总谱
|
|
|
|
|
|
+ /**
|
|
|
|
+ * 如果是作业模式,需要默认渲染当前学生声部对应的声轨,并且默认不显示总谱
|
|
|
|
+ * 2025.02.28 补充逻辑,作业支持用户切换声轨,如果切换了声轨,则选中用户切换后的声轨,用户切换声轨后,url链接会带有part-index参数,
|
|
|
|
+ * 通过有没有part-index区分作业有没有切换声轨,如果没有切换声轨,则还是默认选中学生当前声部的声轨
|
|
|
|
+ */
|
|
if (state.isHomeWork && storeData.user?.instrumentId) {
|
|
if (state.isHomeWork && storeData.user?.instrumentId) {
|
|
- const currentTrack = res.data.musicSheetSoundList.find((item: any) => item.musicalInstrumentId === storeData.user?.instrumentId)?.track;
|
|
|
|
- if (currentTrack) {
|
|
|
|
- partIndex = tracks.findIndex(item => item === currentTrack) || partIndex
|
|
|
|
- state.defaultScoreRender = false
|
|
|
|
|
|
+ if (!query["part-index"]) {
|
|
|
|
+ const currentTrack = res.data.musicSheetSoundList.find((item: any) => item.musicalInstrumentId === storeData.user?.instrumentId)?.track;
|
|
|
|
+ if (currentTrack) {
|
|
|
|
+ partIndex = tracks.findIndex(item => item === currentTrack) || partIndex
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ state.defaultScoreRender = false
|
|
}
|
|
}
|
|
// 设置音源 track 为当前的声轨 index为当前的
|
|
// 设置音源 track 为当前的声轨 index为当前的
|
|
const { track, index, musicalInstrumentId } = state.isSimplePage ? { track:tracks[0], index: state.partIndex, musicalInstrumentId: '' } : initMusicSource(res.data, tracks, partIndex, workRecordInstrumentId)
|
|
const { track, index, musicalInstrumentId } = state.isSimplePage ? { track:tracks[0], index: state.partIndex, musicalInstrumentId: '' } : initMusicSource(res.data, tracks, partIndex, workRecordInstrumentId)
|
|
// 这里返回的track可能和实际的对不上,所以重新筛选一下
|
|
// 这里返回的track可能和实际的对不上,所以重新筛选一下
|
|
const realTrack = musicalInstrumentId && res.data?.musicalInstruments?.length ? res.data?.musicalInstruments.find((item: any) => item?.id == musicalInstrumentId)?.code?.split(',')?.[0] : '';
|
|
const realTrack = musicalInstrumentId && res.data?.musicalInstruments?.length ? res.data?.musicalInstruments.find((item: any) => item?.id == musicalInstrumentId)?.code?.split(',')?.[0] : '';
|
|
|
|
+ const instrumentCodes = musicalInstrumentId && res.data?.musicalInstruments?.length ? res.data?.musicalInstruments.find((item: any) => item?.id == musicalInstrumentId)?.code : '';
|
|
const musicInfo = {
|
|
const musicInfo = {
|
|
...res.data,
|
|
...res.data,
|
|
- track: res.data.musicSheetType === 'CONCERT' ? track : realTrack
|
|
|
|
|
|
+ track: res.data.musicSheetType === 'CONCERT' ? track : realTrack,
|
|
|
|
+ instrumentCodes,
|
|
};
|
|
};
|
|
console.log("🚀 ~ musicInfo:", musicInfo);
|
|
console.log("🚀 ~ musicInfo:", musicInfo);
|
|
setState(musicInfo, index);
|
|
setState(musicInfo, index);
|
|
@@ -1720,7 +1546,7 @@ function initMusicSource(data: any, tracks: string[], partIndex: number, workRec
|
|
}
|
|
}
|
|
/* 目前 管乐迷没有用到 后台生成的节拍器 */
|
|
/* 目前 管乐迷没有用到 后台生成的节拍器 */
|
|
// 当使用节拍器的时候才加载节拍器音频
|
|
// 当使用节拍器的时候才加载节拍器音频
|
|
- if(state.isMixBeat && false) {
|
|
|
|
|
|
+ if(state.isMixBeat) {
|
|
Object.assign(state.beatSong, {
|
|
Object.assign(state.beatSong, {
|
|
music: musicObj?.audioBeatMixUrl,
|
|
music: musicObj?.audioBeatMixUrl,
|
|
accompany: accompanyObj?.audioBeatMixUrl,
|
|
accompany: accompanyObj?.audioBeatMixUrl,
|
|
@@ -1830,7 +1656,10 @@ const setState = (data: any, index: number) => {
|
|
if (state.isSimplePage) {
|
|
if (state.isSimplePage) {
|
|
state.isCombineRender = false;
|
|
state.isCombineRender = false;
|
|
}
|
|
}
|
|
- setCustom(state.isCombineRender ? data.musicSheetSoundList?.length : 0);
|
|
|
|
|
|
+ // 多分轨合并显示的曲子,有可能只有一个原音文件,minCombineNum的最小值至少为2
|
|
|
|
+ const minCombineNum = data.musicSheetSoundList?.length ? Math.max(data.musicSheetSoundList?.length, 2) : 2;
|
|
|
|
+ setCustom(state.isCombineRender ? minCombineNum : 0);
|
|
|
|
+ // setCustom(state.isCombineRender ? data.musicSheetSoundList?.length : 0);
|
|
// 解析扩展字段
|
|
// 解析扩展字段
|
|
if (data.extConfigJson) {
|
|
if (data.extConfigJson) {
|
|
try {
|
|
try {
|
|
@@ -1895,7 +1724,37 @@ const setState = (data: any, index: number) => {
|
|
* 获取指法code
|
|
* 获取指法code
|
|
*/
|
|
*/
|
|
// const code = state.isConcert ? matchVoicePart(state.trackId, "CONCERT") : matchVoicePart(state.musicalCodeId, "SINGLE");
|
|
// const code = state.isConcert ? matchVoicePart(state.trackId, "CONCERT") : matchVoicePart(state.musicalCodeId, "SINGLE");
|
|
- const code = matchVoicePart(state.trackId, "CONCERT")
|
|
|
|
|
|
+
|
|
|
|
+ // 如果是midi的曲子,midi的曲子没有musicSheetSoundList原音列表,指法需要通过musicalInstruments字段判断
|
|
|
|
+ if (data.musicSheetType === "SINGLE" && data.playMode === 'MIDI' && data.musicalInstruments?.length) {
|
|
|
|
+ const currentInstrumentId = query.instrumentId || storeData.user?.instrumentId;
|
|
|
|
+ let midiTrackId = null
|
|
|
|
+ if (currentInstrumentId) {
|
|
|
|
+ midiTrackId = data.musicalInstruments.find((item: any) => item.id == currentInstrumentId)?.code?.split(',')?.[0]
|
|
|
|
+ } else {
|
|
|
|
+ midiTrackId = data.musicalInstruments[0]?.code?.split(',')?.[0]
|
|
|
|
+ }
|
|
|
|
+ state.trackId = midiTrackId || state.trackId
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let code = matchVoicePart(state.trackId, "CONCERT")
|
|
|
|
+ /**
|
|
|
|
+ * 曲子:中音萨克斯教程2-4,返回的乐器code是"Alto Sax,Alto Saxophone",使用第一个Alto Sax去找,找不到对应的指法,这种情况下需要使用多个code去匹配指法
|
|
|
|
+ * 如果当前的第一code找不到,用instrumentCodes去找,
|
|
|
|
+ *
|
|
|
|
+ * */
|
|
|
|
+ if ( data.instrumentCodes && (code == 1 || !code) ) {
|
|
|
|
+ for (let name of data.instrumentCodes.split(',')) {
|
|
|
|
+ let matchCode = matchVoicePart(name, "CONCERT")
|
|
|
|
+ if (matchCode && matchCode !== 1) {
|
|
|
|
+ code = matchCode
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (code == 1 || !code) {
|
|
|
|
+ code = fixInstrumentNameCode(state.trackId)
|
|
|
|
+ }
|
|
state.fingeringInfo = subjectFingering(code);
|
|
state.fingeringInfo = subjectFingering(code);
|
|
console.log("🚀 ~ state.fingeringInfo:", code, state.fingeringInfo, state.trackId, state.track);
|
|
console.log("🚀 ~ state.fingeringInfo:", code, state.fingeringInfo, state.trackId, state.track);
|
|
state.musicalCodeId = state.fingeringInfo?.id || 0
|
|
state.musicalCodeId = state.fingeringInfo?.id || 0
|
|
@@ -2375,6 +2234,7 @@ export const checkMoveNoSave = async () => {
|
|
|
|
|
|
/** 刷新谱面 */
|
|
/** 刷新谱面 */
|
|
export const refreshMusicSvg = () => {
|
|
export const refreshMusicSvg = () => {
|
|
|
|
+ (window as any).DYhideTrackTune = false;
|
|
moveData.noteCoords = []
|
|
moveData.noteCoords = []
|
|
moveData.modelList = []
|
|
moveData.modelList = []
|
|
clearSelection();
|
|
clearSelection();
|