|
@@ -504,6 +504,10 @@ const state = reactive({
|
|
|
loadingText: '音频资源加载中,请稍后…',
|
|
|
/** 是否是简单的单行谱模式页面 */
|
|
|
isSimplePage: false,
|
|
|
+ /** xml的速度和后台设置的速度,计算出的基础音频播放倍率 */
|
|
|
+ originAudioPlayRate: 1,
|
|
|
+ /** 开始播放时,记录的mp3播放倍率,用户当前设置的速度/当前小节的速度 */
|
|
|
+ basePlayRate: 1,
|
|
|
});
|
|
|
const browserInfo = browser();
|
|
|
let offset_duration = 0;
|
|
@@ -579,6 +583,35 @@ export const onEnded = () => {
|
|
|
autoResetPlay();
|
|
|
};
|
|
|
|
|
|
+// 根据当前小节动态设置,右上角展示的速度
|
|
|
+const dynamicShowPlaySpeed = (index: number) => {
|
|
|
+ const item: any = state.times[index];
|
|
|
+ if (item && item.measureSpeed ) {
|
|
|
+ state.playIngSpeed = Math.floor(state.basePlayRate * item.measureSpeed)
|
|
|
+ state.speed = state.playIngSpeed
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 开始播放时,计算mp3的播放倍率
|
|
|
+export const initSetPlayRate = () => {
|
|
|
+ const item: any = (state.sectionStatus && state.section.length === 2) ? state.sectionFirst || state.section[0] : state.times[state.activeNoteIndex];
|
|
|
+ if (item && item.measureSpeed) {
|
|
|
+ const ratio = state.speed / item.measureSpeed
|
|
|
+ // state.audiosInstance?.setSpeed(ratio)
|
|
|
+ state.basePlayRate = ratio || 1;
|
|
|
+ console.log('播放倍率',state.basePlayRate)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 重置播放倍率
|
|
|
+export const resetBaseRate = () => {
|
|
|
+ const currentItem: any = state.times[0];
|
|
|
+ const currentSpeed = currentItem?.measureSpeed ? currentItem.measureSpeed : state.originSpeed;
|
|
|
+ state.speed = currentSpeed
|
|
|
+ //state.activeNoteIndex = 0
|
|
|
+ state.basePlayRate = 1;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* 播放一直触发的事件
|
|
|
*/
|
|
@@ -587,17 +620,8 @@ const handlePlaying = () => {
|
|
|
const duration = getAudioDuration();
|
|
|
state.playProgress = (currentTime / duration) * 100;
|
|
|
let item = getNote(currentTime);
|
|
|
- // console.log(11111,currentTime,duration,state.playSource, item)
|
|
|
- // console.log(item?.i,item?.noteId,item?.measureSpeed,'播放')
|
|
|
- // 练习模式下,实时刷新小节速度
|
|
|
- if (item && state.modeType === "practise" && state.playState === "play" && item.measureSpeed && item.measureSpeed !== state.playIngSpeed) {
|
|
|
- const ratio = state.speed / state.originSpeed
|
|
|
- state.playIngSpeed = Math.ceil(ratio * item.measureSpeed) || state.speed
|
|
|
- } else if (state.modeType === "practise" && state.playState === "play" && item && !item.measureSpeed) {
|
|
|
- state.playIngSpeed = state.speed
|
|
|
- }
|
|
|
- state.playIngSpeed = state.playIngSpeed || state.speed;
|
|
|
if (item) {
|
|
|
+ dynamicShowPlaySpeed(item.i);
|
|
|
// 选段状态下
|
|
|
if (state.sectionStatus && state.section.length === 2) {
|
|
|
// 如果开启了预备拍
|
|
@@ -640,6 +664,8 @@ const handlePlaying = () => {
|
|
|
// #8698 bug修复
|
|
|
if (state.modeType === "practise" && state.sectionStatus) {
|
|
|
onEnded();
|
|
|
+ state.activeNoteIndex = state.sectionFirst ? state.sectionFirst.i : state.section[0].i
|
|
|
+ dynamicShowPlaySpeed(state.activeNoteIndex)
|
|
|
resetPlaybackToStart();
|
|
|
return;
|
|
|
}
|
|
@@ -669,6 +695,10 @@ export const skipNotePlay = async (itemIndex: number, isStart = false) => {
|
|
|
itemTime = 0;
|
|
|
}
|
|
|
if (item) {
|
|
|
+ // 非选段模式,点击音符,动态设置右下角的速度
|
|
|
+ if (item.measureSpeed && state.section.length < 2) {
|
|
|
+ state.speed = Math.floor(state.basePlayRate * item.measureSpeed)
|
|
|
+ }
|
|
|
setAudioCurrentTime(itemTime, itemIndex);
|
|
|
// 一行谱,点击音符,或者播放完成,需要跳转音符位置
|
|
|
gotoNext(item, true);
|
|
@@ -752,6 +782,7 @@ export const togglePlay = async (playState?: "play" | "paused", sourceType?: str
|
|
|
clearSelection();
|
|
|
}
|
|
|
}
|
|
|
+ initSetPlayRate();
|
|
|
audioListStart(state.playState);
|
|
|
return true;
|
|
|
};
|
|
@@ -994,14 +1025,20 @@ export const handleResetPlay = () => {
|
|
|
if (state.isAppPlay) {
|
|
|
audioData.progress = 0
|
|
|
}
|
|
|
+ resetBaseRate();
|
|
|
resetPlaybackToStart();
|
|
|
// 如果是暂停, 直接播放
|
|
|
togglePlay("play");
|
|
|
};
|
|
|
/** 设置速度 */
|
|
|
export const handleSetSpeed = (speed: number) => {
|
|
|
- setStorageSpeed(state.examSongId, speed);
|
|
|
+ // setStorageSpeed(state.examSongId, speed);
|
|
|
state.speed = speed;
|
|
|
+ // 当前的音符
|
|
|
+ const currentItem: any = (state.sectionStatus && state.section.length === 2) ? state.sectionFirst || state.section[0] : state.times[state.activeNoteIndex];
|
|
|
+ state.basePlayRate = currentItem?.measureSpeed ? state.speed / currentItem.measureSpeed : state.speed / state.originSpeed;
|
|
|
+ const actualRate = state.originAudioPlayRate * state.basePlayRate;
|
|
|
+ console.log('速度设置',speed,'小节计算的倍率',state.basePlayRate,'实际播放倍率',actualRate)
|
|
|
};
|
|
|
/** 清除选段状态 */
|
|
|
export const clearSelection = () => {
|
|
@@ -1352,7 +1389,7 @@ const setState = (data: any, index: number) => {
|
|
|
if (state.isAppPlay) {
|
|
|
state.enableEvaluation = state.midiUrl ? true : false
|
|
|
} else {
|
|
|
- state.enableEvaluation = state.accompany ? true : false
|
|
|
+ state.enableEvaluation = state.accompany || state.music ? true : false
|
|
|
}
|
|
|
state.isConcert = data.musicSheetType === "CONCERT" ? true : false;
|
|
|
// multiTracksSelection 返回为空,默认代表全部分轨
|
|
@@ -1620,11 +1657,12 @@ watch(
|
|
|
() => state.activeMeasureIndex,
|
|
|
() => {
|
|
|
// 需要减去的合并小节数
|
|
|
- const needReduceMultipleRestNum = getNeedReduceMultipleRestNum(state.activeMeasureIndex)
|
|
|
- const matchMeasureNum = state.activeMeasureIndex - needReduceMultipleRestNum - 1
|
|
|
- console.log('选中的小节',matchMeasureNum,'需要减去的小节',needReduceMultipleRestNum,'当前的小节',state.activeMeasureIndex)
|
|
|
+ // const needReduceMultipleRestNum = getNeedReduceMultipleRestNum(state.activeMeasureIndex)
|
|
|
+ // const matchMeasureNum = state.activeMeasureIndex - needReduceMultipleRestNum - 1
|
|
|
+ // console.log('选中的小节',matchMeasureNum,'需要减去的小节',needReduceMultipleRestNum,'当前的小节',state.activeMeasureIndex)
|
|
|
state.vfmeasures.forEach((item: any, idx: number) => {
|
|
|
- if (idx === matchMeasureNum) {
|
|
|
+ const measureNum = item.getAttribute('data-num') ? Number(item.getAttribute('data-num')) : 1;
|
|
|
+ if (measureNum === state.activeMeasureIndex) {
|
|
|
item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#132D4C")
|
|
|
item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#040D1E")
|
|
|
} else {
|
|
@@ -1637,18 +1675,14 @@ watch(
|
|
|
leftMeasureNumberXML = state.section[1].MeasureNumberXML
|
|
|
rightMeasureNumberXML = state.section[0].MeasureNumberXML
|
|
|
}
|
|
|
- const leftVfmeasuresIndex = leftMeasureNumberXML - getNeedReduceMultipleRestNum(leftMeasureNumberXML) - 1
|
|
|
- const rightVfmeasuresIndex = rightMeasureNumberXML - getNeedReduceMultipleRestNum(rightMeasureNumberXML) - 1
|
|
|
- if(idx >= leftVfmeasuresIndex && idx <= rightVfmeasuresIndex){
|
|
|
+ if(measureNum >= leftMeasureNumberXML && measureNum <= rightMeasureNumberXML){
|
|
|
item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
|
|
|
item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#2B70A5")
|
|
|
}
|
|
|
// 预备小节
|
|
|
- if(state.sectionFirst){
|
|
|
- const sectionFirstVfmeasuresIndex = state.sectionFirst.MeasureNumberXML - getNeedReduceMultipleRestNum(state.sectionFirst.MeasureNumberXML) - 1
|
|
|
- const sectionFirstDom = state.vfmeasures[sectionFirstVfmeasuresIndex]
|
|
|
- sectionFirstDom?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
|
|
|
- sectionFirstDom?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
|
|
|
+ if(state.sectionFirst && measureNum === state.sectionFirst.MeasureNumberXML){
|
|
|
+ item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
|
|
|
+ item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
|
|
|
}
|
|
|
}else{
|
|
|
item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
|
|
@@ -1672,32 +1706,29 @@ watch(
|
|
|
leftMeasureNumberXML = state.section[1].MeasureNumberXML
|
|
|
rightMeasureNumberXML = state.section[0].MeasureNumberXML
|
|
|
}
|
|
|
- const leftVfmeasuresIndex = leftMeasureNumberXML - getNeedReduceMultipleRestNum(leftMeasureNumberXML) - 1
|
|
|
- const rightVfmeasuresIndex = rightMeasureNumberXML - getNeedReduceMultipleRestNum(rightMeasureNumberXML) - 1
|
|
|
state.vfmeasures.forEach((item: any, idx: number) => {
|
|
|
+ const measureNum = item.getAttribute('data-num') ? Number(item.getAttribute('data-num')) : 1;
|
|
|
// 小于选中置灰
|
|
|
- if (idx < leftVfmeasuresIndex) {
|
|
|
+ if (measureNum < leftMeasureNumberXML) {
|
|
|
item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(96,159,207,0.5)")
|
|
|
item.querySelector('.vf-custom-bot')?.setAttribute("fill", "rgba(43,112,165,0.5)")
|
|
|
}
|
|
|
// 大于选中置灰
|
|
|
- if(idx > rightVfmeasuresIndex){
|
|
|
+ if(measureNum > rightMeasureNumberXML){
|
|
|
item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(96,159,207,0.5)")
|
|
|
item.querySelector('.vf-custom-bot')?.setAttribute("fill", "rgba(43,112,165,0.5)")
|
|
|
}
|
|
|
+ // 预备小节
|
|
|
+ if(state.sectionFirst && measureNum === state.sectionFirst.MeasureNumberXML){
|
|
|
+ item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
|
|
|
+ item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
|
|
|
+ }
|
|
|
})
|
|
|
- // 预备小节
|
|
|
- if(state.sectionFirst){
|
|
|
- const sectionFirstVfmeasuresIndex = state.sectionFirst.MeasureNumberXML - getNeedReduceMultipleRestNum(state.sectionFirst.MeasureNumberXML) - 1
|
|
|
- const sectionFirstDom = state.vfmeasures[sectionFirstVfmeasuresIndex]
|
|
|
- sectionFirstDom?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
|
|
|
- sectionFirstDom?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
|
|
|
- }
|
|
|
}else{
|
|
|
// 恢复选段前
|
|
|
- const matchMeasureNum = state.activeMeasureIndex - getNeedReduceMultipleRestNum(state.activeMeasureIndex) - 1
|
|
|
state.vfmeasures.forEach((item: any, idx: number) => {
|
|
|
- if (idx === matchMeasureNum) {
|
|
|
+ const measureNum = item.getAttribute('data-num') ? Number(item.getAttribute('data-num')) : 1;
|
|
|
+ if (measureNum === state.activeMeasureIndex) {
|
|
|
item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#132D4C")
|
|
|
item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#040D1E")
|
|
|
} else {
|