yonge 4 months ago
parent
commit
bff5b10ba4

+ 45 - 2
audio-analysis/src/main/java/com/yonge/netty/dto/UserChannelContext.java

@@ -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;
 		}

+ 23 - 1
audio-analysis/src/main/java/com/yonge/netty/entity/MusicXmlNote.java

@@ -33,7 +33,13 @@ public class MusicXmlNote {
 	private int denominator;
 	
 	private int measureRenderIndex;
-
+	
+	//是否是延音
+	private boolean isTenutoSound;
+	
+	//是否是跳音
+	private boolean isStaccato;
+	
 	public double getTimeStamp() {
 		return timeStamp;
 	}
@@ -113,4 +119,20 @@ public class MusicXmlNote {
 	public void setMeasureRenderIndex(int measureRenderIndex) {
 		this.measureRenderIndex = measureRenderIndex;
 	}
+
+	public boolean isTenutoSound() {
+		return isTenutoSound;
+	}
+
+	public void setIsTenutoSound(boolean isTenutoSound) {
+		this.isTenutoSound = isTenutoSound;
+	}
+
+	public boolean isStaccato() {
+		return isStaccato;
+	}
+
+	public void setIsStaccato(boolean isStaccato) {
+		this.isStaccato = isStaccato;
+	}
 }