yonge 3 年之前
父節點
當前提交
f524cf199d

+ 12 - 1
audio-analysis/src/main/java/com/yonge/nettty/dto/ChunkAnalysis.java

@@ -13,13 +13,16 @@ public class ChunkAnalysis {
 	private double splDb;
 
 	private float power;
+	
+	private float amplitude;
 
-	public ChunkAnalysis(double startTime, double endTime, double frequency, double splDb, float power) {
+	public ChunkAnalysis(double startTime, double endTime, double frequency, double splDb, float power, float amplitude) {
 		this.startTime = startTime;
 		this.endTime = endTime;
 		this.frequency = frequency;
 		this.splDb = splDb;
 		this.power = power;
+		this.amplitude = amplitude;
 		this.durationTime = endTime - startTime;
 	}
 
@@ -76,4 +79,12 @@ public class ChunkAnalysis {
 	public void setPower(float power) {
 		this.power = power;
 	}
+
+	public float getAmplitude() {
+		return amplitude;
+	}
+
+	public void setAmplitude(float amplitude) {
+		this.amplitude = amplitude;
+	}
 }

+ 10 - 13
audio-analysis/src/main/java/com/yonge/nettty/dto/NoteAnalysis.java

@@ -1,8 +1,5 @@
 package com.yonge.nettty.dto;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import com.ym.mec.common.enums.BaseEnum;
 
 public class NoteAnalysis {
@@ -46,8 +43,6 @@ public class NoteAnalysis {
 
 	private NoteErrorType noteErrorType = NoteErrorType.RIGHT;
 
-	private List<Double> chunkFrequencyList = new ArrayList<Double>();
-
 	private double playDurationTime;
 	
 	private int score;
@@ -59,6 +54,8 @@ public class NoteAnalysis {
 	private int integrityScore;
 
 	private boolean ignore;
+	
+	private ChunkAnalysis lastChunkAnalysis;
 
 	public NoteAnalysis(int index, int sectionIndex, double frequency, double standardDurationTime) {
 		this.standardDurationTime = standardDurationTime;
@@ -162,14 +159,6 @@ public class NoteAnalysis {
 		this.playDurationTime = playDurationTime;
 	}
 
-	public List<Double> getChunkFrequencyList() {
-		return chunkFrequencyList;
-	}
-
-	public void setChunkFrequencyList(List<Double> chunkFrequencyList) {
-		this.chunkFrequencyList = chunkFrequencyList;
-	}
-
 	public NoteErrorType getMusicalErrorType() {
 		return noteErrorType;
 	}
@@ -210,4 +199,12 @@ public class NoteAnalysis {
 		this.integrityScore = integrityScore;
 	}
 
+	public ChunkAnalysis getLastChunkAnalysis() {
+		return lastChunkAnalysis;
+	}
+
+	public void setLastChunkAnalysis(ChunkAnalysis lastChunkAnalysis) {
+		this.lastChunkAnalysis = lastChunkAnalysis;
+	}
+
 }

+ 12 - 1
audio-analysis/src/main/java/com/yonge/nettty/dto/SectionAnalysis.java

@@ -16,15 +16,18 @@ public class SectionAnalysis {
 	// 得分
 	private float score;
 	
+	private boolean isIngore;
+	
 	public SectionAnalysis() {
 		// TODO Auto-generated constructor stub
 	}
 
-	public SectionAnalysis(int index, int noteNum, float durationTime, float score) {
+	public SectionAnalysis(int index, int noteNum, float durationTime, float score, boolean isIngore) {
 		this.measureIndex = index;
 		this.noteNum = noteNum;
 		this.durationTime = durationTime;
 		this.score = score;
+		this.isIngore = isIngore;
 	}
 
 	public int getIndex() {
@@ -59,6 +62,14 @@ public class SectionAnalysis {
 		this.score = score;
 	}
 	
+	public boolean isIngore() {
+		return isIngore;
+	}
+
+	public void setIsIngore(boolean isIngore) {
+		this.isIngore = isIngore;
+	}
+
 	@Override
 	public String toString() {
 		return ToStringBuilder.reflectionToString(this);

+ 229 - 103
audio-analysis/src/main/java/com/yonge/nettty/dto/UserChannelContext.java

@@ -38,6 +38,8 @@ public class UserChannelContext implements PitchDetectionHandler {
 	
 	private Long recordId;
 	
+	private Integer subjectId;
+	
 	// 曲目与musicxml对应关系
 	private ConcurrentHashMap<Integer, MusicXmlBasicInfo> songMusicXmlMap = new ConcurrentHashMap<Integer, MusicXmlBasicInfo>();
 
@@ -57,12 +59,12 @@ public class UserChannelContext implements PitchDetectionHandler {
 	
 	private double receivedTime;
 	
-	private List<Integer> firstNoteIndexPerSectionList;
-	
 	private List<ChunkAnalysis> chunkAnalysisList = new ArrayList<ChunkAnalysis>();
 	
+	private ChunkAnalysis lastChunkAnalysis;
+	
 	public void init(){
-		firstNoteIndexPerSectionList = getFirstNoteIndexPerSection(null);
+
 	}
 	
 	public Long getRecordId() {
@@ -73,6 +75,10 @@ public class UserChannelContext implements PitchDetectionHandler {
 		this.recordId = recordId;
 	}
 
+	public void setSubjectId(Integer subjectId) {
+		this.subjectId = subjectId;
+	}
+
 	public ConcurrentHashMap<Integer, MusicXmlBasicInfo> getSongMusicXmlMap() {
 		return songMusicXmlMap;
 	}
@@ -110,8 +116,10 @@ public class UserChannelContext implements PitchDetectionHandler {
 		doneSectionAnalysisList = new ArrayList<SectionAnalysis>();
 		chunkAnalysisList = new ArrayList<ChunkAnalysis>();
 		recordId = null;
+		subjectId = null;
 		playTime = 0;
 		receivedTime = 0;
+		lastChunkAnalysis = null;
 	}
 	
 	public MusicXmlBasicInfo getMusicXmlBasicInfo(Integer songId){
@@ -243,7 +251,7 @@ public class UserChannelContext implements PitchDetectionHandler {
 		double playFrequency = frequencyDetector.getFrequency(samples);
 		double splDb = Signals.soundPressureLevel(samples);
 		float power = Signals.power(samples);
-		float energy = Signals.energy(samples);
+		float amplitude = Signals.norm(samples);
 		
 		double durationTime = 1000 * (samples.length * 2) / audioFormat.getSampleRate() / (audioFormat.getSampleSizeInBits() / 8);
 		
@@ -278,70 +286,39 @@ public class UserChannelContext implements PitchDetectionHandler {
 					noteAnalysis.setIgnore(true);
 				}
 
-				if(noteAnalysis.getChunkFrequencyList().size() > 0){
-					noteAnalysis.setPlayFrequency(computeFrequency(noteAnalysis.getChunkFrequencyList(), 10));
-				}
-				
-				final double avgFrequency = noteAnalysis.getPlayFrequency();
+				noteAnalysis.setPlayFrequency(computeFrequency(chunkAnalysisList, 10));
 				
 				//判断节奏(音符持续时间内有不间断的音高,就节奏正确)
-				ChunkAnalysis chunkAnalysis = null;
-				boolean tempo = false;
-				boolean isContinue = true;
-				for (int i = 0; i < chunkAnalysisList.size(); i++) {
-					chunkAnalysis = chunkAnalysisList.get(i);
-					if (chunkAnalysis != null) {
-						if (chunkAnalysis.getFrequency() > 100) {
-							tempo = true;
-							if (isContinue == false) {
-								tempo = false;
-								break;
-							}
+				boolean tempo = true;
+				if (musicXmlNote.getFrequency() == -1) {// 休止符
+					tempo = chunkAnalysisList.stream().filter(t -> t.getAmplitude() > 5).count() == 0;
+				} else {
+					if (subjectId == 23) {
+						if (lastChunkAnalysis == null) {
+							tempo = computeTempoWithAmplitude(chunkAnalysisList, 0);
 						} else {
-							if (tempo == true) {
-								isContinue = false;
-							}
+							tempo = computeTempoWithAmplitude(chunkAnalysisList, lastChunkAnalysis.getAmplitude());
 						}
-					}
-				}
-				
-				if (tempo) {
-					// 获取上一个音符信息
-					if (doneNoteAnalysisList.size() > 0) {
-						NoteAnalysis lastNoteAnalysis = doneNoteAnalysisList.get(doneNoteAnalysisList.size() - 1);
-						if (lastNoteAnalysis != null) {
-							double pf = lastNoteAnalysis.getPlayFrequency();
-							int continueSize = 0;
-							for (int i = 0; i < chunkAnalysisList.size(); i++) {
-								chunkAnalysis = chunkAnalysisList.get(i);
-								if (chunkAnalysis != null) {
-									if (Math.abs(chunkAnalysis.getFrequency() - pf) > 10) {
-										break;
-									}
-									continueSize++;
-								}
-							}
-							if(continueSize * 100 / chunkAnalysisList.size() > 40){
-								tempo = false;
-							}
+					} else {
+						NoteAnalysis lastNoteAnalysis = null;
+						if (doneNoteAnalysisList.size() > 0) {
+							lastNoteAnalysis = doneNoteAnalysisList.get(doneNoteAnalysisList.size() - 1);
 						}
+						tempo = computeTempoWithFrequency(chunkAnalysisList, lastNoteAnalysis);
 					}
 				}
 				
 				noteAnalysis.setTempo(tempo);
 				
-				/*long wrongChunkSize = chunkAnalysisList.stream().filter(t -> Math.abs(t.getFrequency() - avgFrequency) > 10).count();
-				if(wrongChunkSize * 100 /chunkAnalysisList.size() > 40){
-					noteAnalysis.setTempo(false);
-				}
-				*/
 				evaluateForNote(noteAnalysis);
 
-				LOGGER.info("当前音符下标[{}] 预计频率:{} 实际频率:{} 持续时间:{}", noteAnalysis.getMusicalNotesIndex(), musicXmlNote.getFrequency(), noteAnalysis.getPlayFrequency(),
-						noteAnalysis.getDurationTime() - durationTime);
+				LOGGER.info("当前音符下标[{}] 预计频率:{} 实际频率:{} 节奏:{}", noteAnalysis.getMusicalNotesIndex(), musicXmlNote.getFrequency(), noteAnalysis.getPlayFrequency(),
+						noteAnalysis.isTempo());
 				
 				doneNoteAnalysisList.add(noteAnalysis);
 				
+				lastChunkAnalysis = chunkAnalysisList.get(chunkAnalysisList.size() - 1);
+				
 				chunkAnalysisList.clear();
 
 				// 准备处理下一个音符
@@ -355,10 +332,6 @@ public class UserChannelContext implements PitchDetectionHandler {
 				}
 				
 				NoteAnalysis nextNoteAnalysis = new NoteAnalysis(nextNoteIndex, getMusicSectionIndex(null, nextNoteIndex), nextNoteFrequence, standDuration);
-				/*if (noteAnalysis.isTempo() == true && wrongChunkSize == 0) {
-					nextNoteAnalysis.setTempo(false);
-					LOGGER.info("节奏错误:频率没变");
-				}*/
 
 				noteAnalysis = nextNoteAnalysis;
 
@@ -371,20 +344,13 @@ public class UserChannelContext implements PitchDetectionHandler {
 				}*/
 				//skip = noteAnalysis.getStandardDurationTime() * 0.2;
 				
-				LOGGER.info("Frequency:{}  splDb:{}  Power:{}  energy:{}", playFrequency, splDb, power, energy);
+				LOGGER.info("Frequency:{}  splDb:{}  Power:{}  amplitude:{}", playFrequency, splDb, power, amplitude);
 				
-				/*int chunkSize = noteAnalysis.getChunkFrequencyList().size();
-				if (chunkSize > 0 && Math.abs(noteAnalysis.getChunkFrequencyList().stream().mapToDouble(t -> t).sum() / chunkSize - playFrequency) > 10) {
-					noteAnalysis.setTempo(false);
-					LOGGER.info("节奏错误:频率发生变化");
-				}*/
-
 				if (playFrequency < 2000 && playFrequency > 100) {
-					noteAnalysis.getChunkFrequencyList().add(playFrequency);
 					noteAnalysis.setPlayDurationTime(noteAnalysis.getPlayDurationTime() + durationTime);
 				}
 				
-				chunkAnalysisList.add(new ChunkAnalysis(receivedTime - durationTime, receivedTime, playFrequency, splDb, power));
+				chunkAnalysisList.add(new ChunkAnalysis(receivedTime - durationTime, receivedTime, playFrequency, splDb, power, amplitude));
 				
 			}
 
@@ -403,6 +369,8 @@ public class UserChannelContext implements PitchDetectionHandler {
 		
 		float power = Signals.power(samples);
 		
+		float energy = Signals.energy(samples);
+		
 		LOGGER.info("Frequency:{}  SplDb:{}  Power:{}", frequency, splDb, power);
 		
 		double durationTime = 1000 * (samples.length * 2) / audioFormat.getSampleRate() / (audioFormat.getSampleSizeInBits() / 8);
@@ -433,7 +401,7 @@ public class UserChannelContext implements PitchDetectionHandler {
 			}
 		}
 		
-		chunkAnalysisList.add(new ChunkAnalysis(startTime, startTime + durationTime, frequency, splDb, power));
+		chunkAnalysisList.add(new ChunkAnalysis(startTime, startTime + durationTime, frequency, splDb, power, energy));
 	}
 
 	@Override
@@ -462,14 +430,14 @@ public class UserChannelContext implements PitchDetectionHandler {
 		noteAnalysis.setDurationTime(noteDurationTime);
 		
 		if(pitch != -1){
-			noteAnalysis.getChunkFrequencyList().add((double) pitch);
+			//noteAnalysis.getChunkFrequencyList().add((double) pitch);
 		}
 		
 		setProcessingNote(noteAnalysis);
 		
 		if(noteAnalysis.getMusicalNotesIndex() <= getTotalMusicNoteIndex(null) && noteDurationTime >= musicXmlNote.getDuration()){
 			
-			noteAnalysis.setPlayFrequency(noteAnalysis.getChunkFrequencyList().stream().mapToDouble(t -> t).sum()/noteAnalysis.getChunkFrequencyList().size());
+			//noteAnalysis.setPlayFrequency(noteAnalysis.getChunkFrequencyList().stream().mapToDouble(t -> t).sum()/noteAnalysis.getChunkFrequencyList().size());
 			
 			LOGGER.info("当前音符下标[{}] 预计频率:{} 实际频率:{} 持续时间:{}", noteAnalysis.getMusicalNotesIndex() , musicXmlNote.getFrequency(), noteAnalysis.getPlayFrequency(), noteAnalysis.getDurationTime());
 			
@@ -518,10 +486,13 @@ public class UserChannelContext implements PitchDetectionHandler {
 		
 		//取出当前小节的所有音符
 		List<NoteAnalysis> noteAnalysisList = doneNoteAnalysisList.stream().filter(t -> t.getSectionIndex() == sectionIndex).collect(Collectors.toList());
+		
+		long ignoreSize = doneNoteAnalysisList.stream().filter(t -> t.isIgnore()).count();
 
 		SectionAnalysis sectionAnalysis = new SectionAnalysis();
 		sectionAnalysis.setIndex(sectionIndex);
 		sectionAnalysis.setNoteNum(noteAnalysisList.size());
+		sectionAnalysis.setIsIngore(ignoreSize == noteAnalysisList.size());
 		
 		//判断是否需要评分
 		MusicXmlSection musicXmlSection = getCurrentMusicSection(null, sectionIndex);
@@ -585,16 +556,38 @@ public class UserChannelContext implements PitchDetectionHandler {
 
 	public void evaluateForNote(NoteAnalysis noteAnalysis){
 		
-		if (noteAnalysis.getPlayDurationTime() / noteAnalysis.getDurationTime() < 0.1) {
-			noteAnalysis.setMusicalErrorType(NoteErrorType.NOT_PLAY);
-		} else if (noteAnalysis.getPlayDurationTime() / noteAnalysis.getDurationTime() < 0.5) {
-			noteAnalysis.setMusicalErrorType(NoteErrorType.INTEGRITY_WRONG);
-		} else if (!noteAnalysis.isTempo()) {
-			noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
-		} else if (Math.abs(noteAnalysis.getFrequency() - noteAnalysis.getPlayFrequency()) > 10) {
-			noteAnalysis.setMusicalErrorType(NoteErrorType.INTONATION_WRONG);
+		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()) {
+				noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
+			} else if (Math.abs(noteAnalysis.getFrequency() - noteAnalysis.getPlayFrequency()) > 10) {
+				noteAnalysis.setMusicalErrorType(NoteErrorType.INTONATION_WRONG);
+			} else {
+				noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
+			}
 		} else {
-			noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
+			if (subjectId == 23) {
+				if (!noteAnalysis.isTempo()) {
+					noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
+				} else {
+					noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
+				}
+			} else {
+				if (noteAnalysis.getPlayDurationTime() / noteAnalysis.getDurationTime() < 0.1) {
+					noteAnalysis.setMusicalErrorType(NoteErrorType.NOT_PLAY);
+				} else if (noteAnalysis.getPlayDurationTime() / noteAnalysis.getDurationTime() < 0.6) {
+					noteAnalysis.setMusicalErrorType(NoteErrorType.INTEGRITY_WRONG);
+				} else if (!noteAnalysis.isTempo()) {
+					noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
+				} else if (Math.abs(noteAnalysis.getFrequency() - noteAnalysis.getPlayFrequency()) > 10) {
+					noteAnalysis.setMusicalErrorType(NoteErrorType.INTONATION_WRONG);
+				} else {
+					noteAnalysis.setMusicalErrorType(NoteErrorType.RIGHT);
+				}
+			}
 		}
 		
 		//计算音分
@@ -625,14 +618,25 @@ public class UserChannelContext implements PitchDetectionHandler {
 			noteAnalysis.setIntegrityScore(integrityScore);
 		}
 		noteAnalysis.setIntonationScore(intonationScore);
-		noteAnalysis.setScore((int)((intonationScore + tempoScore + integrityScore) / 3));
+		if (subjectId == 23) {
+			noteAnalysis.setScore((int)tempoScore);
+		}else{
+			noteAnalysis.setScore((int)((intonationScore + tempoScore + integrityScore) / 3));
+		}
 	}
 	
-	private double computeFrequency(List<Double> chunkFrequencyList, int offsetRange) {
+	private double computeFrequency(List<ChunkAnalysis> chunkAnalysisList, int offsetRange) {
 
+		List<Double> chunkFrequencyList = chunkAnalysisList.stream().map(t -> t.getFrequency()).filter(t -> t.doubleValue() > 100 && t.doubleValue() < 2000)
+				.collect(Collectors.toList());
+		
+		if (chunkFrequencyList.size() == 0) {
+			return -1;
+		}
+		
 		// 排序
 		chunkFrequencyList = chunkFrequencyList.stream().sorted().collect(Collectors.toList());
-
+		
 		double tempFrequency = chunkFrequencyList.get(0), totalFrequency = chunkFrequencyList.get(0);
 
 		int maxChunkSize = 0;
@@ -643,7 +647,7 @@ public class UserChannelContext implements PitchDetectionHandler {
 			tempFrequency = chunkFrequencyList.get(i);
 
 			if (Math.abs(avgFrequency - tempFrequency) > offsetRange) {
-				
+
 				avgFrequency = totalFrequency / chunkSize;
 
 				if (maxChunkSize < chunkSize) {
@@ -658,8 +662,8 @@ public class UserChannelContext implements PitchDetectionHandler {
 				chunkSize++;
 				totalFrequency += tempFrequency;
 			}
-			
-			if(i == chunkFrequencyList.size() - 1){
+
+			if (i == chunkFrequencyList.size() - 1) {
 				if (maxChunkSize <= chunkSize) {
 					maxChunkSize = chunkSize;
 					frequency = avgFrequency;
@@ -667,30 +671,152 @@ public class UserChannelContext implements PitchDetectionHandler {
 			}
 		}
 
-		if (maxChunkSize * 100 / chunkFrequencyList.size() < 40) {
-			return chunkFrequencyList.stream().collect(Collectors.summingDouble(t -> t)) / chunkFrequencyList.size();
+		if (chunkFrequencyList.size() < 3 || maxChunkSize * 100 / chunkFrequencyList.size() < 40) {
+			frequency = chunkFrequencyList.stream().collect(Collectors.summingDouble(t -> t)) / chunkFrequencyList.size();
+		}
+		
+		if(frequency < 100){
+			frequency = -1;
 		}
 
 		return frequency;
 	}
+
+	private boolean computeTempoWithFrequency(List<ChunkAnalysis> chunkAnalysisList, NoteAnalysis lastNoteAnalysis){
+		ChunkAnalysis chunkAnalysis = null;
+		boolean tempo = false;
+		boolean isContinue = true;
+		boolean lastestNotePlayStatus = true;
+		int unplayedSize = 0;
+		for (int i = 0; i < chunkAnalysisList.size(); i++) {
+			chunkAnalysis = chunkAnalysisList.get(i);
+			if (chunkAnalysis != null) {
+				if (chunkAnalysis.getFrequency() > 100) {
+					tempo = true;
+					if (isContinue == false) {
+						if (chunkAnalysisList.size() < 5) {
+							if (unplayedSize > 0) {
+								tempo = false;
+								break;
+							}
+						} else {
+							if ((unplayedSize * 100 / chunkAnalysisList.size()) > 10 || unplayedSize > 1) {
+								tempo = false;
+								break;
+							}
+						}
+					}
+				} else {
+					if (tempo == true) {
+						isContinue = false;
+						unplayedSize++;
+					}
+				}
+				if(i == chunkAnalysisList.size() - 1){
+					lastestNotePlayStatus = false;
+				}
+			}
+		}
+		
+		if (tempo && lastestNotePlayStatus) {
+			// 获取上一个音符信息
+			if (lastNoteAnalysis != null) {
+				double pf = lastNoteAnalysis.getPlayFrequency();
+				int continueSize = 0;
+				for (int i = 0; i < chunkAnalysisList.size(); i++) {
+					chunkAnalysis = chunkAnalysisList.get(i);
+					if (chunkAnalysis != null) {
+						if (Math.abs(chunkAnalysis.getFrequency() - pf) > 10) {
+							break;
+						}
+						continueSize++;
+					}
+				}
+				if(continueSize * 100 / chunkAnalysisList.size() > 40){
+					tempo = false;
+				}
+			}
+		}
+		
+		return tempo;
+	}
+	
+	private boolean computeTempoWithAmplitude(List<ChunkAnalysis> chunkAnalysisList, float lastChunkAmplitude) {
+
+		boolean tempo = false;
+
+		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;
+		}
+
+		// 检测是否有多个波峰
+		int peakSize = 0;
+		int minPeakIndex = chunkAmplitudeList.size() - 1;
+		for (int i = 0; i < chunkAmplitudeList.size() - 1; i++) {
+			if (chunkAmplitudeList.get(i) < 5) {
+				continue;
+			}
+			if (i == 0) {
+				if (lastChunkAmplitude > 0 && chunkAmplitudeList.get(i) > lastChunkAmplitude) {
+					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;
+				}
+			}
+
+			if (i == chunkAmplitudeList.size() - 2) {
+				if (chunkAmplitudeList.get(i) < chunkAmplitudeList.get(i + 1)) {
+					peakSize++;
+					if (minPeakIndex > i) {
+						minPeakIndex = i;
+					}
+				}
+			}
+		}
+
+		tempo = peakSize == 1;
+
+		// 检测是否延迟进入
+		if (tempo == true) {
+			if ((minPeakIndex + 1) * 100 / chunkAmplitudeList.size() > 40 && chunkAmplitudeList.size() > 3) {
+				tempo = false;
+			}
+		}
+
+		return tempo;
+	}
 	
-	private double majorityElement(List<Double> nums) {
-	    double major = nums.get(0);
-	    int count = 1;
-
-	    for(int i = 1; i < nums.size(); i++) {
-	        double num = nums.get(i);
-	        if(count == 0) {
-	            count++;
-	            major = num;
-	        } else if(major == num) {
-	            count++;
-	        } else {
-	            count--;
-	        }
-	    }
-
-	    return major;
+	private boolean getPeak(List<Float> chunkList, float last){
+		
+		if(chunkList.size()<3){
+			return true;
+		}
+		
+		int peakSize = 0;
+		for(int i = 0;i<chunkList.size() - 1;i++){
+			if(i == 0){
+				if(chunkList.get(i) > last){
+					peakSize++;
+				}
+			}
+			else if(chunkList.get(i-1) < chunkList.get(i) && chunkList.get(i) >= chunkList.get(i + 1)){
+				peakSize++;
+			}
+			
+			if(i == chunkList.size() - 2){
+				if(chunkList.get(i) < chunkList.get(i + 1)){
+					peakSize++;
+				}
+			}
+		}
+		
+		return peakSize == 1;
 	}
 	
 }

+ 12 - 6
audio-analysis/src/main/java/com/yonge/netty/server/messagehandler/TextWebSocketHandler.java

@@ -10,6 +10,7 @@ import java.math.BigDecimal;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.stream.Collectors;
@@ -112,6 +113,7 @@ public class TextWebSocketHandler extends SimpleChannelInboundHandler<TextWebSoc
 				sysMusicCompareRecord.setSourceTime((float) ((musicXmlNote.getTimeStamp()+musicXmlNote.getDuration())/1000));
 				sysMusicCompareRecordService.insert(sysMusicCompareRecord);
 				channelContext.setRecordId(sysMusicCompareRecord.getId());
+				channelContext.setSubjectId(musicXmlBasicInfo.getSubjectId());
 			}
 			break;
 		case "recordEnd": // 结束评测
@@ -141,12 +143,14 @@ public class TextWebSocketHandler extends SimpleChannelInboundHandler<TextWebSoc
 				if(sysMusicCompareRecord != null){
 					musicXmlBasicInfo = channelContext.getMusicXmlBasicInfo(null);
 					
-					sysMusicCompareRecord.setScore(new BigDecimal(scoreMap.get("score")));
-					sysMusicCompareRecord.setIntonation(new BigDecimal(scoreMap.get("intonation")));
-					sysMusicCompareRecord.setIntegrity(new BigDecimal(scoreMap.get("integrity")));
-					sysMusicCompareRecord.setCadence(new BigDecimal(scoreMap.get("cadence")));
+					if (scoreMap != null && scoreMap.size() > 1) {
+						sysMusicCompareRecord.setScore(new BigDecimal(scoreMap.get("score")));
+						sysMusicCompareRecord.setIntonation(new BigDecimal(scoreMap.get("intonation")));
+						sysMusicCompareRecord.setIntegrity(new BigDecimal(scoreMap.get("integrity")));
+						sysMusicCompareRecord.setCadence(new BigDecimal(scoreMap.get("cadence")));
+						sysMusicCompareRecord.setPlayTime(scoreMap.get("playTime") / 1000);
+					}
 					sysMusicCompareRecord.setFeature(FeatureType.CLOUD_STUDY_EVALUATION);
-					sysMusicCompareRecord.setPlayTime(scoreMap.get("playTime")/1000);
 
 		            String url = null;
 		            try {
@@ -159,7 +163,9 @@ public class TextWebSocketHandler extends SimpleChannelInboundHandler<TextWebSoc
 					//sysMusicCompareRecord.setVideoFilePath(videoFilePath);
 
 					Map<String, Object> scoreData = new HashMap<>();
-					scoreData.put("userMeasureScore", channelContext.getDoneSectionAnalysisList().stream().collect(Collectors.toMap(SectionAnalysis :: getIndex, t -> t)));
+					List<SectionAnalysis> sectionAnalysisList = channelContext.getDoneSectionAnalysisList();
+					sectionAnalysisList = sectionAnalysisList.stream().filter(t -> t.isIngore() == false).collect(Collectors.toList());
+					scoreData.put("userMeasureScore", sectionAnalysisList.stream().collect(Collectors.toMap(SectionAnalysis :: getIndex, t -> t)));
 
 					Map<String, Object> musicalNotesPlayStats = new HashMap<>();
 					musicalNotesPlayStats.put("detailId", musicXmlBasicInfo.getDetailId());