|
@@ -3,6 +3,7 @@ package com.yonge.nettty.dto;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.HashMap;
|
|
|
+import java.util.Iterator;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Map.Entry;
|
|
@@ -285,8 +286,13 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
if (musicXmlNote.getDontEvaluating()) {
|
|
|
noteAnalysis.setIgnore(true);
|
|
|
}
|
|
|
+
|
|
|
+ NoteAnalysis lastNoteAnalysis = null;
|
|
|
+ if (doneNoteAnalysisList.size() > 0) {
|
|
|
+ lastNoteAnalysis = doneNoteAnalysisList.get(doneNoteAnalysisList.size() - 1);
|
|
|
+ }
|
|
|
|
|
|
- noteAnalysis.setPlayFrequency(computeFrequency(chunkAnalysisList, 10));
|
|
|
+ noteAnalysis.setPlayFrequency(computeFrequency(chunkAnalysisList, lastNoteAnalysis, 10));
|
|
|
|
|
|
//判断节奏(音符持续时间内有不间断的音高,就节奏正确)
|
|
|
boolean tempo = true;
|
|
@@ -300,10 +306,6 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
tempo = computeTempoWithAmplitude(chunkAnalysisList, lastChunkAnalysis.getAmplitude());
|
|
|
}
|
|
|
} else {
|
|
|
- NoteAnalysis lastNoteAnalysis = null;
|
|
|
- if (doneNoteAnalysisList.size() > 0) {
|
|
|
- lastNoteAnalysis = doneNoteAnalysisList.get(doneNoteAnalysisList.size() - 1);
|
|
|
- }
|
|
|
tempo = computeTempoWithFrequency(chunkAnalysisList, lastNoteAnalysis);
|
|
|
}
|
|
|
}
|
|
@@ -557,13 +559,11 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
public void evaluateForNote(NoteAnalysis noteAnalysis){
|
|
|
|
|
|
if (noteAnalysis.getFrequency() == -1) {// 休止符
|
|
|
- if (1 - noteAnalysis.getPlayDurationTime() / noteAnalysis.getDurationTime() < 0.1) {
|
|
|
- noteAnalysis.setMusicalErrorType(NoteErrorType.NOT_PLAY);
|
|
|
- } else if (1 - noteAnalysis.getPlayDurationTime() / noteAnalysis.getDurationTime() < 0.6) {
|
|
|
- noteAnalysis.setMusicalErrorType(NoteErrorType.INTEGRITY_WRONG);
|
|
|
- } else if (!noteAnalysis.isTempo()) {
|
|
|
+ if (!noteAnalysis.isTempo()) {
|
|
|
noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
|
- } else if (Math.abs(noteAnalysis.getFrequency() - noteAnalysis.getPlayFrequency()) > 10) {
|
|
|
+ }else if (1 - noteAnalysis.getPlayDurationTime() / noteAnalysis.getDurationTime() < 0.6) {
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.INTEGRITY_WRONG);
|
|
|
+ } else if (Math.abs(noteAnalysis.getFrequency() - noteAnalysis.getPlayFrequency()) > 10) {
|
|
|
noteAnalysis.setMusicalErrorType(NoteErrorType.INTONATION_WRONG);
|
|
|
} else {
|
|
|
noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
|
|
@@ -625,7 +625,7 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private double computeFrequency(List<ChunkAnalysis> chunkAnalysisList, int offsetRange) {
|
|
|
+ private double computeFrequency(List<ChunkAnalysis> chunkAnalysisList, NoteAnalysis lastNoteAnalysis, int offsetRange) {
|
|
|
|
|
|
List<Double> chunkFrequencyList = chunkAnalysisList.stream().map(t -> t.getFrequency()).filter(t -> t.doubleValue() > 100 && t.doubleValue() < 2000)
|
|
|
.collect(Collectors.toList());
|
|
@@ -634,6 +634,16 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ // 剔除上一个音延续到下一个音
|
|
|
+ double lastFrequency = lastNoteAnalysis.getFrequency();
|
|
|
+ Iterator<Double> iterable = chunkFrequencyList.iterator();
|
|
|
+ while(iterable.hasNext()){
|
|
|
+ if(Math.abs(lastFrequency - iterable.next()) > 10){
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ iterable.remove();
|
|
|
+ }
|
|
|
+
|
|
|
// 排序
|
|
|
chunkFrequencyList = chunkFrequencyList.stream().sorted().collect(Collectors.toList());
|
|
|
|
|
@@ -700,7 +710,7 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
break;
|
|
|
}
|
|
|
} else {
|
|
|
- if ((unplayedSize * 100 / chunkAnalysisList.size()) > 10 || unplayedSize > 1) {
|
|
|
+ if ((unplayedSize * 100 / chunkAnalysisList.size()) > 10 || unplayedSize > 2) {
|
|
|
tempo = false;
|
|
|
break;
|
|
|
}
|
|
@@ -748,14 +758,14 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
List<Float> chunkAmplitudeList = chunkAnalysisList.stream().map(ChunkAnalysis::getAmplitude).collect(Collectors.toList());
|
|
|
|
|
|
if (chunkAmplitudeList.size() < 3) {
|
|
|
- return chunkAmplitudeList.stream().filter(t -> t.floatValue() > 5).count() > 0;
|
|
|
+ return chunkAmplitudeList.stream().filter(t -> t.floatValue() > 3).count() > 0;
|
|
|
}
|
|
|
|
|
|
// 检测是否有多个波峰
|
|
|
int peakSize = 0;
|
|
|
- int minPeakIndex = chunkAmplitudeList.size() - 1;
|
|
|
- for (int i = 0; i < chunkAmplitudeList.size() - 1; i++) {
|
|
|
- if (chunkAmplitudeList.get(i) < 5) {
|
|
|
+ int minPeakIndex = -1;
|
|
|
+ for (int i = 0; i < chunkAmplitudeList.size(); i++) {
|
|
|
+ if (chunkAmplitudeList.get(i) < 3) {
|
|
|
continue;
|
|
|
}
|
|
|
if (i == 0) {
|
|
@@ -763,24 +773,24 @@ public class UserChannelContext implements PitchDetectionHandler {
|
|
|
peakSize++;
|
|
|
minPeakIndex = i;
|
|
|
}
|
|
|
- } else if (chunkAmplitudeList.get(i - 1) < chunkAmplitudeList.get(i) && chunkAmplitudeList.get(i) >= chunkAmplitudeList.get(i + 1)) {
|
|
|
- peakSize++;
|
|
|
- if (minPeakIndex > i) {
|
|
|
- minPeakIndex = i;
|
|
|
+ } else if (i == chunkAmplitudeList.size() - 1) {
|
|
|
+ if (chunkAmplitudeList.get(i) > chunkAmplitudeList.get(i - 1)) {
|
|
|
+ peakSize++;
|
|
|
+ if (minPeakIndex == -1 || minPeakIndex > i) {
|
|
|
+ minPeakIndex = i;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- if (i == chunkAmplitudeList.size() - 2) {
|
|
|
- if (chunkAmplitudeList.get(i) < chunkAmplitudeList.get(i + 1)) {
|
|
|
+ } else {
|
|
|
+ if (chunkAmplitudeList.get(i - 1) < chunkAmplitudeList.get(i) && chunkAmplitudeList.get(i) >= chunkAmplitudeList.get(i + 1)) {
|
|
|
peakSize++;
|
|
|
- if (minPeakIndex > i) {
|
|
|
+ if (minPeakIndex == -1 || minPeakIndex > i) {
|
|
|
minPeakIndex = i;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- tempo = peakSize == 1;
|
|
|
+ tempo = peakSize <= 1;
|
|
|
|
|
|
// 检测是否延迟进入
|
|
|
if (tempo == true) {
|