|
@@ -362,9 +362,10 @@ public class UserChannelContext {
|
|
|
|
|
|
converter.toFloatArray(datas, samples);
|
|
|
|
|
|
+ /**
|
|
|
for(float f : samples) {
|
|
|
floatSamples.add(f);
|
|
|
- }
|
|
|
+ }*/
|
|
|
|
|
|
if (detector == null) {
|
|
|
detector = new FastYin(audioFormat.getSampleRate(), getBufferSize());
|
|
@@ -565,6 +566,11 @@ public class UserChannelContext {
|
|
|
public void evaluateForNote(MusicXmlNote musicXmlNote, NoteAnalysis noteAnalysis, List<ChunkAnalysis> chunkAnalysisList) {
|
|
|
|
|
|
double durationTime = chunkAnalysisList.get(chunkAnalysisList.size() - 1).getEndTime() - chunkAnalysisList.get(0).getStartTime();
|
|
|
+
|
|
|
+ //如果是跳音
|
|
|
+ if(musicXmlNote.isStaccato()) {
|
|
|
+ durationTime = durationTime / 2;
|
|
|
+ }
|
|
|
|
|
|
double playDurationTime = 0;
|
|
|
|
|
@@ -697,6 +703,8 @@ public class UserChannelContext {
|
|
|
|
|
|
LOGGER.debug("---------------------TEMPO----------------------");
|
|
|
|
|
|
+ double playDurationTime = chunkAnalysisList.stream().filter(t -> t.getFrequency() > MIN_FREQUECY).mapToDouble(t -> t.getDurationTime()).sum();
|
|
|
+
|
|
|
ChunkAnalysis firstChunkAnalysis = chunkAnalysisList.get(0);
|
|
|
|
|
|
noteAnalysis.setRhythmStartTime(musicXmlNote.getTimeStamp() + dynamicOffset);//默认值
|
|
@@ -705,6 +713,10 @@ public class UserChannelContext {
|
|
|
|
|
|
if(musicXmlNote.getFrequency() < MIN_FREQUECY) {
|
|
|
if(frequencyRhythmMap.size() == 0) {
|
|
|
+ if((int)playDurationTime > 0) {
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
|
|
|
return 99;
|
|
|
} else {
|
|
@@ -714,6 +726,21 @@ public class UserChannelContext {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if(musicXmlNote.isTenutoSound()) {
|
|
|
+ if(frequencyRhythmMap.size() == 0) {
|
|
|
+ if((int)playDurationTime > 0) {
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
|
|
|
+ return 99;
|
|
|
+ }
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
|
+ LOGGER.debug("根据能量包络检测到[{}]个断点,分别在[{}]", frequencyRhythmMap.size(), frequencyRhythmMap.values().stream().map(value -> value).map(Object::toString).collect(Collectors.joining(",")));
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if(frequencyRhythmMap.size() > 1) {
|
|
|
noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
|
LOGGER.debug("根据音高检测到[{}]个断点,分别在[{}]", frequencyRhythmMap.size(), frequencyRhythmMap.values().stream().map(value -> value).map(Object::toString).collect(Collectors.joining(",")));
|
|
@@ -736,10 +763,26 @@ public class UserChannelContext {
|
|
|
LOGGER.debug("节奏错误原因:进入时间点[{}]太晚", firstBeatTime);
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+ //如果是跳音,只需吹奏一半时值,超过一半则节奏错误
|
|
|
+ if(musicXmlNote.isStaccato()) {
|
|
|
+ double durationTime = musicXmlNote.getDuration();
|
|
|
+
|
|
|
+ if(durationTime / playDurationTime < 2) {
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
|
+ LOGGER.debug("节奏错误原因:断音吹奏时间过长[{}%]" , playDurationTime * 100 / durationTime);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
|
|
|
LOGGER.debug("找到节奏点StartTime:{}", firstBeatTime);
|
|
|
} else {
|
|
|
- noteAnalysis.setMusicalErrorType(NoteErrorType.NOT_PLAY);
|
|
|
+ if((int)playDurationTime == 0) {
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.NOT_PLAY);
|
|
|
+ }else {
|
|
|
+ noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
|
+ }
|
|
|
LOGGER.debug("没有找到节奏点");
|
|
|
return 0;
|
|
|
}
|