MidiScoreView的传统打分界面,只支持普通打分SingIntonationViewer的现代化打分界面,支持更炫的效果,支持五维打分和普通打分MidiScoreView组件:<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.tme.ktv.midi.MidiScoreView
android:id="@+id/midi_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="130dp"/>
</FrameLayout>MidiScoreView并设置Activity:<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/intonation_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:clipToPadding="false"
android:clipChildren="false"
tools:ignore="MissingDefaultResource">
<com.tme.ktv.intonation.view.PerfectAnimView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/karaoke_perfect_view"
/>
<com.tme.ktv.intonation.view.SimpleScoreBar
android:focusable="false"
android:id="@+id/pk_score_bar"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_marginStart="@dimen/pk_score_layout_margin_left"
android:layout_marginTop="160dp" />
<com.tme.ktv.intonation.SingIntonationViewer
android:id="@+id/player_float_intonation_viewer"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_gravity="bottom"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="130dp" />
</FrameLayout>lastStableScore / finalStableScorelastRhythmScore / finalRhythmScoreskillScore / finalSkillScorelastLongToneScore / finalLongToneScoredynamicScore / finalDynamicScoreonDoingMultiScore回调中处理五维分数数据onMultiScoreFinish回调中处理最终五维分数@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMidiScoreView = this.findViewById(R.id.midi_view);
mMidiScoreView.setActivity(this);private class ScoreListenerImpl extends KaraokePlayer.OnScoreListener{
@Override
protected void onPrepareScore(SingCompetitor competitor, int nums) {
//获取到节拍数据,设置给midiView,其中 nums是打分的总句子数,不一定等于歌词行数
mMidiScoreView.initData(competitor);
}
//普通打分单句回调
@Override
protected void onDoingScore(int score, String level, int timeStamp) {
//普通打分的单句实时打分结果,数值和等级
mIntonationDelegate?.postUpdateScore(score,timeStamp.toFloat(),null)
}
//普通打分回调
@Override
protected void onFinishScore(int totalScore, String level) {
//普通打分演唱结束后的总分结果
}
/**
*五维打分回调
* 每唱完一句出一次分数,上一句就是刚唱完的那一句
* @param lastScore 上一句的分数
* @param timeStamp 时间戳
* @param lastLongToneScore 上一句的气息分数
* @param lastRhythmScore 上一句的节奏分数
* @param lastStableScore 上一句的音准分数
* @param dynamicScore 上一句的情感分数
* @param skillScore 上一句的技巧分数
* @param lastSkillTrillCount 上一句命中的颤音个数
* @param lastSkillGlintCount 上一句命中的滑音个数
* @param lastSkillTransliterationCount 上一句命中的转音个数
*/
public void onDoingMultiScore(int lastScore, long timeStamp, int lastLongToneScore, int lastRhythmScore,
int lastStableScore, int dynamicScore, int skillScore,
int lastSkillTrillCount, int lastSkillGlintCount,
int lastSkillTransliterationCount) {
//五维打分实时回调
multiScoreResultInfo.resetLastScore()
multiScoreResultInfo.lastLongToneScore = lastLongToneScore
multiScoreResultInfo.lastRhythmScore = lastRhythmScore
multiScoreResultInfo.lastStableScore = lastStableScore
multiScoreResultInfo.lastDynamicScore = dynamicScore
multiScoreResultInfo.lastSkillScore = skillScore
multiScoreResultInfo.lastSkillTrillCount = lastSkillTrillCount
multiScoreResultInfo.lastSkillTransliterationCount = lastSkillGlintCount
mIntonationDelegate?.postUpdateScore(lastScore, timeStamp.toFloat(), multiScoreResultInfo)
}
/**
* 五维打分结束回调
* @param finalLongToneScore 气息分数
* @param finalRhythmScore 节奏分数
* @param finalStableScore 音准分数
* @param finalDynamicScore 情感分数
* @param finalSkillScore 技巧分数
* @param lastSentenceIndex 最后一句歌词的索引
* @param totalSentences 这首歌的句子数
*/
public void onMultiScoreFinish(int finalLongToneScore, int finalRhythmScore, int finalStableScore,
int finalDynamicScore, int finalSkillScore, int lastSentenceIndex,
int totalSentences) {
}
}
inner class KtvMidiCallbackImpl : KaraokePlayerListener() {
private fun startMidiView() {
if (KtvPlayerConfig.getInstance().isEnableScore) {
log("startMidiView")
midiView.startMidi(viewModel.currPlayer()?.timeLineTime ?: 0)
}
}
private fun stopMidiView() {
midiView.stopMidi()
}
override fun onPlayStart(request: KaraokePlayRequest) {
log("onPlayStart:$request")
if (request.songInfoObject.mNoteBytes == null && request.songInfoObject.songType == SongType.SONG_TYPE_K_SONG) {
log("current song has no noteBytes, close score")
if (MediaProperties.get().isEnableScore) {
PlayConsole.get().setScoreOpen(false)
KGToast.show("该歌曲不支持打分,已为您关闭打分")
}
}
}
override fun onLyricResourceChanged(request: KaraokePlayRequest) {
super.onLyricResourceChanged(request)
stopMidiView()
startMidiView()
}
override fun onResume(mKtvPlayRequest: KaraokePlayRequest) {
log("call onResume")
startMidiView()
}
override fun onPause(mKtvPlayRequest: KaraokePlayRequest) {
log("onPause")
stopMidiView()
}
override fun onPlayEnd(request: KaraokePlayRequest, endInfo: PlayEndInfo) {
Log.e(TAG, "onPlayEnd")
mHandler.post {
stopMidiView()
midiView.releaseMidi()
val openScore =
viewModel.currSongInfo().value?.mNoteBytes != null && viewModel.currSongInfo().value?.songType == SongType.SONG_TYPE_K_SONG
if (!openScore && endInfo.isPlayFinish) {
playNextIfNeed()
}
}
}
override fun onSeekComplete(request: KaraokePlayRequest, position: Long) {
log("onPlayPositionChange currentTime $position ")
midiView.seekMidi(position)
}
override fun onBufferingStart(request: KaraokePlayRequest?) {
stopMidiView()
}
override fun onBufferingEnd(request: KaraokePlayRequest?) {
startMidiView()
}
}
需要把两个实现添加到播放器中
karaokePlayer.addCallback(CallbackImpl())
karaokePlayer.addOnScoreListener(ScoreListenerImpl())MidiScoreView.getIntonationViewGroup().getIntonationView().getIntonationViewerParam();
val intonationViewerParam = midiView.intonationViewGroup.intonationView.intonationViewerParam
midiView.midiViewHeight = DisplayUtil.dp2px(140f)
midiView.midiViewBackgroundColor = getActivity()?.resources?.getColor(R.color.ktv_brown) ?: -1
val missPaint = Paint()
missPaint.color = Color.parseColor("#234512")
missPaint.strokeWidth = DisplayUtil.dp2px(8.0F).toFloat()
intonationViewerParam.noteMissPaint = missPaint
val hitPaint = Paint()
hitPaint.color = Color.parseColor("#666666")
hitPaint.strokeWidth = DisplayUtil.dp2px(8.0F).toFloat()
intonationViewerParam.noteHitPaint = hitPaintsongType设置为SONG_TYPE_K_SONG(录唱模式),其他模式不支持打分。isPollMode),用于多屏一起唱的场景。在轮询模式下,需要实现ScoreResultRequester接口来获取打分数据。MidiScoreView.setActivity(this),否则会影响动画效果。releaseMidi()释放资源。songInfoObject.mNoteBytes是否为null判断歌曲是否支持打分,通过songInfoObject.mOriginalMultiScoreContent是否为null判断歌曲是否支持五维打分。