Browse Source

演唱 总谱可以根据声轨播放

黄琪勇 3 tuần trước cách đây
mục cha
commit
792cad2705

+ 30 - 5
src/page-instrument/header-top/index.tsx

@@ -855,6 +855,19 @@ export default defineComponent({
               style={{ display: playTypeBtn.value.display ? "" : "none" }}
               class={["driver-2", styles.btn, playTypeBtn.value.disabled && styles.disabled, styles.playType]}
               onClick={() => {
+                // 总谱 并且开启了单个声轨音频时候
+                if(state.isCombineRender && audioData.combineIndex !== "-1") {
+                  audioData.combineIndex = "-1"
+                  state.music = ""
+                  // 有总谱范唱就切换到总谱范唱
+                  if(audioData.scoreAudioUrl){
+                    state.fanSong = audioData.scoreAudioUrl
+                    audioData.songCollection.fanSongEle = audioData.scoreAudioEle
+                    audioData.songCollection.beatFanSongEle = audioData.beatScoreAudioEle
+                  }else{
+                    state.fanSong = ""
+                  }
+                }
                 const oldPlayType = state.playType;
                 headTopData.oldPlayType = oldPlayType;
                 const oldPlaySource = state.playSource;
@@ -898,6 +911,23 @@ export default defineComponent({
               style={{ display: originBtn.value.display ? "" : "none" }}
               class={["driver-3", styles.btn, originBtn.value.disabled && styles.disabled, state.playType === "play" ? styles.playSource : styles.songSource]}
               onClick={async () => {
+                // 总谱 并且开启了单个声轨音频时候
+                if(state.isCombineRender && audioData.combineIndex !== "-1") {
+                  audioData.combineIndex = "-1"
+                  // 区分演奏和演唱
+                  if(state.playType === "play") {
+                    state.music = ""
+                  }else{
+                    // 有总谱范唱就切换到总谱范唱
+                    if(audioData.scoreAudioUrl){
+                      state.fanSong = audioData.scoreAudioUrl
+                      audioData.songCollection.fanSongEle = audioData.scoreAudioEle
+                      audioData.songCollection.beatFanSongEle = audioData.beatScoreAudioEle
+                    }else{
+                      state.fanSong = ""
+                    }
+                  }
+                }
                 const oldPlayType = state.playType;
                 const oldPlaySource = state.playSource;
                 if (state.playType === "play") {
@@ -918,11 +948,6 @@ export default defineComponent({
                   }
                 }
                 await handlerModeChange(oldPlayType, oldPlaySource);
-                // 总谱 并且开启了单个声轨音频时候
-                if(state.isCombineRender && state.playSource === "background") {
-                  audioData.combineIndex = -1
-                  state.music = ""
-                }
                 showToast({
                   message: state.playType === "play" ? (state.playSource === "music" ? "已切换为原声" : state.playSource === "background" ? "已切换为伴奏" : "已切换为唱名") : state.playSource === "music" ? "已切换为范唱" : state.playSource === "background" ? "已切换为伴唱" : "已切换为唱名",
                   position: "top",

+ 12 - 0
src/state.ts

@@ -1327,17 +1327,29 @@ function initMusicSource(data: any, tracks: string[], partIndex: number, workRec
         if(state.combinePartIndexs.length) {
           // 当选择多个分轨时候
           state.combinePartIndexs.map( partI => {
+            // 演奏
             const musicSheetSound = musicSheetSoundList.find((item:any)=>{
               return item.track?.toLowerCase().trim() === tracks[partI]?.toLowerCase().trim() && item.audioPlayType === "PLAY"
             })
             musicSheetSound?.audioFileUrl && (audioData.combineMusics[partI] = musicSheetSound.audioFileUrl)
+            // 演唱
+            const singMusicSheetSound = musicSheetSoundList.find((item:any)=>{
+              return item.track?.toLowerCase().trim() === tracks[partI]?.toLowerCase().trim() && item.audioPlayType === "SING"
+            })
+            singMusicSheetSound?.audioFileUrl && (audioData.combineMusics[`sing_${partI}`] = singMusicSheetSound.audioFileUrl)
           })
         }else{
           tracks.map((itemTrack:any, partI:number) => {
+            // 演奏
             const musicSheetSound = musicSheetSoundList.find((item:any)=>{
               return item.track?.toLowerCase().trim() === itemTrack?.toLowerCase().trim() && item.audioPlayType === "PLAY"
             })
             musicSheetSound?.audioFileUrl && (audioData.combineMusics[partI] = musicSheetSound.audioFileUrl)
+            // 演唱
+            const singMusicSheetSound = musicSheetSoundList.find((item:any)=>{
+              return item.track?.toLowerCase().trim() === itemTrack?.toLowerCase().trim() && item.audioPlayType === "SING"
+            })
+            singMusicSheetSound?.audioFileUrl && (audioData.combineMusics[`sing_${partI}`] = singMusicSheetSound.audioFileUrl)
           })
         }
         // 总谱演奏模式是 伴奏

+ 55 - 35
src/view/audio-list/index.tsx

@@ -46,9 +46,12 @@ export const audioData = reactive({
 		beatMingSongEle: null as HTMLAudioElement | null,
 		beatMingSongGirlEle: null as HTMLAudioElement | null
 	},
-	combineIndex: -1, // 当前 播放的总谱音频索引
+	combineIndex: "-1", // 当前 播放的总谱音频索引
 	combineMusics: {} as Record<string, any>, // 音频 url
-	combineMusicEles:[] as {key:number, value:HTMLAudioElement, beatValue:HTMLAudioElement|null}[] // 存储的音频el 当大于4个时候删除
+	combineMusicEles:[] as {key:string, value:HTMLAudioElement, beatValue:HTMLAudioElement|null}[], // 存储的音频el 当大于4个时候删除
+	scoreAudioUrl:"",  // 总谱范唱 存一个备份
+	scoreAudioEle: null as HTMLAudioElement | null,  // 总谱范唱 存一个备份
+	beatScoreAudioEle: null as HTMLAudioElement | null,  // 总谱范唱节拍器 存一个备份
 });
 const midiRef = ref();
 /** 播放或暂停 */
@@ -326,12 +329,6 @@ export const handleLoadBeatMusic = async () => {
 	state.loadingText = "音频资源加载中,请稍后…"
 	state.isLoading = true
 	const musicAudio = await mergeBeatAudio(currentMusic) as any
-	const playEleObj = {
-		"play_music":"beatSongEle",
-		"play_background":"beatBackgroundEle",
-		"sing_music":"beatFanSongEle",
-		"sing_background":"beatBanSongEle"
-	}
 	// 给音频赋值
 	if(playSource === "mingSong"){
 		// 当男声女声都有的时候 才区分
@@ -364,22 +361,39 @@ export const handleLoadBeatMusic = async () => {
 			}
 		}
 		// @ts-ignore
-		audioData.songCollection[playEleObj[`${playType}_${playSource}`]] = musicAudio
+		audioData.songCollection[beatPlayObj[`${playType}_${playSource}`]] = musicAudio
+		// 总谱范唱需要保存一份备份
+		if(audioData.combineIndex === "-1" && playType === "sing" && playSource==="music" ){
+			audioData.beatScoreAudioEle = musicAudio
+		}
 	}
 	state.isLoading = false
 }
 
 // 切换对应的声轨,并且配置当前的audio
-export async function changeCombineAudio (combineIndex: number){
+export async function changeCombineAudio (combineIndex: string){
 	// 重复点击的时候取消选中 原音
 	if(combineIndex === audioData.combineIndex){
-		audioData.combineIndex = -1
-		state.playSource = "background"
-		state.music = ""
+		audioData.combineIndex = "-1"
+		// 区分演奏和演唱
+		if(state.playType === "play") {
+			state.playSource = "background"
+			state.music = ""
+		}else{
+			// 有总谱范唱就切换到总谱范唱
+			if(audioData.scoreAudioUrl){
+				state.fanSong = audioData.scoreAudioUrl
+				audioData.songCollection.fanSongEle = audioData.scoreAudioEle
+				audioData.songCollection.beatFanSongEle = audioData.beatScoreAudioEle
+			}else{
+				state.playSource = "background"
+				state.fanSong = ""
+			}
+		}
 		// 当开启节拍器的时候,切为伴奏的时候合成节拍器1
 		await handleLoadBeatMusic()
 		// 当没有背景音文件的时候
-		if(!state.accompany) {
+		if(!state.accompany && !state.fanSong && !state.banSong) {
 			state.noMusicSource = true
 		}
 		return
@@ -393,28 +407,23 @@ export async function changeCombineAudio (combineIndex: number){
 	})
 	const cacheMusic = audioData.combineMusicEles[cacheMusicIndex]
 	if(cacheMusic?.value){
-		audioData.songCollection.songEle = cacheMusic.value
-		audioData.songCollection.beatSongEle = cacheMusic.beatValue
+		if(state.playType === "play") {
+			audioData.songCollection.songEle = cacheMusic.value
+			audioData.songCollection.beatSongEle = cacheMusic.beatValue
+		}else{
+			audioData.songCollection.fanSongEle = cacheMusic.value
+			audioData.songCollection.beatFanSongEle = cacheMusic.beatValue
+		}
 		// 使用缓存之后 当前数据位置向后偏移,删除缓存的时候以使用顺序位置
 		const itemMusic = audioData.combineMusicEles.splice(cacheMusicIndex, 1)
 		audioData.combineMusicEles.push(...itemMusic)
 	}else{
 		const music = await createAudio(musicUrl)
 		const beatMusic = await mergeBeatAudio(musicUrl) as any 
-		// 当没有背景音的时候 需要绑定事件
-		if(!audioData.songCollection.backgroundEle){
-			if(music){
-				music.addEventListener("play", onPlay);
-				music.addEventListener("ended", onEnded);
-			}			
-		}
-		// 取消掉背景音绑定的时候,然后给当前原音节拍音频绑定事件,这样防止没有背景节拍的时候,能给
-		if(beatMusic){
-			audioData.songCollection.beatBackgroundEle?.removeEventListener("play", onPlay)
-			audioData.songCollection.beatBackgroundEle?.removeEventListener("ended", onEnded)
-			beatMusic.addEventListener("play", onPlay);
-			beatMusic.addEventListener("ended", onEnded);
-		}
+		music?.addEventListener("play", onPlay);
+		music?.addEventListener("ended", onEnded);
+		beatMusic?.addEventListener("play", onPlay);
+		beatMusic?.addEventListener("ended", onEnded);
 		audioData.combineMusicEles.push({
 			key: combineIndex,
 			value: music!,
@@ -424,18 +433,27 @@ export async function changeCombineAudio (combineIndex: number){
 		if(audioData.combineMusicEles.length > 4){
 			audioData.combineMusicEles.splice(0,1)
 		}
-		audioData.songCollection.songEle = music
-		audioData.songCollection.beatSongEle = beatMusic!
+		if(state.playType === "play") {
+			audioData.songCollection.songEle = music
+			audioData.songCollection.beatSongEle = beatMusic!
+		}else{
+			audioData.songCollection.fanSongEle = music
+			audioData.songCollection.beatFanSongEle = beatMusic!
+		}
 	}
 	audioData.combineIndex = combineIndex
-	state.music = musicUrl
+	if(state.playType === "play"){
+		state.music = musicUrl
+	}else{
+		state.fanSong = musicUrl
+	}
 	state.playSource = "music"
 	// 当没有背景音文件的时候
-	if(!state.accompany) {
+	if(!state.accompany && !state.fanSong && !state.banSong) {
 		state.noMusicSource = false
 	}
 	showToast({
-		message:  "已开启原声",
+		message:  state.playType === "play" ? "已开启原声" : "已开启范唱",
 		position: "top",
 		className: "selectionToast",
 	});
@@ -567,6 +585,8 @@ export default defineComponent({
 					banSongEle:banSong,
 					mingSongEle:mingSong
 				})
+				audioData.scoreAudioUrl = state.fanSong
+				audioData.scoreAudioEle = fanSong
 				Object.assign(audioData.mingSongTypeCollection, {
 					mingSongEle: mingSong,
 					mingSongGirlEle:mingSongGirl

+ 15 - 12
src/view/music-score/combineAudio/index.tsx

@@ -8,7 +8,7 @@ import state from "/src/state"
 export default defineComponent({
    name: "combineAudio",
    setup(props, { emit }) {
-      const elementsData = ref<{ index: number; top: number; left: number }[]>([])
+      const elementsData = ref<{ index: string; top: number; left: number }[]>([])
       onMounted(() => {
          const parent = document.querySelector("#osmdCanvasPage1")
          const elements = document.querySelectorAll("g[data-trackIdx]")
@@ -19,17 +19,20 @@ export default defineComponent({
          const combineMusicsIndexs = Object.keys(audioData.combineMusics)
          elements.forEach(element => {
             const dataTrackIdx = element.getAttribute("data-trackIdx")
-            // 当有 dataTrackIdx 并且有原音的时候 显示
-            if (dataTrackIdx && combineMusicsIndexs.includes(dataTrackIdx)) {
-               const elementRect = element.getBoundingClientRect()
-               const height = elementRect.height
-               let top = elementRect.top + height / 2 - 11 - musicContainerPos.top
-               let left = elementRect.left - 22 - 10 - musicContainerPos.left
-               elementsData.value.push({
-                  index: parseInt(dataTrackIdx),
-                  top: top,
-                  left: left
-               })
+            // 当有 dataTrackIdx 并且有原音的时候 显示  区分演奏演唱
+            if (dataTrackIdx) {
+               const musIndex = state.playType === "sing" ? `sing_${dataTrackIdx}` : dataTrackIdx
+               if (combineMusicsIndexs.includes(musIndex)) {
+                  const elementRect = element.getBoundingClientRect()
+                  const height = elementRect.height
+                  let top = elementRect.top + height / 2 - 11 - musicContainerPos.top
+                  let left = elementRect.left - 22 - 10 - musicContainerPos.left
+                  elementsData.value.push({
+                     index: musIndex,
+                     top: top,
+                     left: left
+                  })
+               }
             }
          })
       })

+ 1 - 1
src/view/music-score/index.tsx

@@ -272,7 +272,7 @@ export default defineComponent({
 				{slots.default?.()}
 				{props.showSelection && musicData.showSelection && !state.isEvaluatReport &&!state.isSimplePage && state.musicRendered && <Selection />}
 				{/* 目前只有演奏模式下有 */}
-				{props.showSelection && musicData.showSelection && state.isCombineRender &&!state.isSimplePage && !state.isPreView && state.musicRendered && state.playType === "play" && <CombineAudio></CombineAudio> }
+				{props.showSelection && musicData.showSelection && state.isCombineRender &&!state.isSimplePage && !state.isPreView && state.musicRendered && <CombineAudio></CombineAudio> }
 			</div>
 		);
 	},