| 
					
				 | 
			
			
				@@ -6,6 +6,7 @@ import be.tarsos.dsp.pitch.PitchProcessor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import be.tarsos.dsp.util.PitchConverter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.alibaba.fastjson.JSON; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.alibaba.fastjson.JSONObject; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.alibaba.fastjson.serializer.SerializerFeature; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ym.mec.biz.dal.config.SoundCompareConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ym.mec.biz.dal.dao.SysMusicScoreAccompanimentDao; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ym.mec.biz.dal.dto.*; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -31,7 +32,6 @@ import org.springframework.web.socket.WebSocketSession; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import javax.sound.sampled.UnsupportedAudioFileException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.io.File; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.io.FileNotFoundException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.io.IOException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.io.RandomAccessFile; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.math.BigDecimal; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -50,7 +50,7 @@ import static com.ym.mec.biz.service.SoundSocketService.VIDEO_UPDATE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Service 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private final Logger LOGGER = LoggerFactory.getLogger(SoundCompareHandler.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final Logger LOGGER = LoggerFactory.getLogger(SoundCompareHandler.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private BigDecimal oneHundred = new BigDecimal(100); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -99,6 +99,9 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 userSoundInfoMap.get(phone).setMusicXmlInfos(musicXmlInfos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 musicXmlInfos = musicXmlInfos.stream().filter(m->!m.getDontEvaluating()).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 userSoundInfoMap.get(phone).setMusicScoreId(bodyObject.getInteger("id")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if(bodyObject.containsKey("beatLength")){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userSoundInfoMap.get(phone).setFirstMeasureStartBytes((long) (bodyObject.getLong("beatLength")/1000f*(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate()))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if(bodyObject.containsKey("platform")){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     userSoundInfoMap.get(phone).setDeviceType(DeviceTypeEnum.valueOf(bodyObject.getString("platform"))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -148,8 +151,9 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     File file = new File(tmpDir+phone + "_"+ userSoundInfoMap.get(phone).getMusicScoreId() +"_"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +".wav"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     userSoundInfoMap.get(phone).setFile(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     userSoundInfoMap.get(phone).setAccessFile(new RandomAccessFile(file, "rw")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userSoundInfoMap.get(phone).getAccessFile().seek(44); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     userSoundInfoMap.get(phone).setRecordFilePath(file.getAbsolutePath()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } catch (FileNotFoundException e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } catch (IOException e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     throw new BizException("文件创建失败:", e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 break; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -178,10 +182,10 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 createHeader(phone, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             case SoundSocketService.PROXY_MESSAGE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(DeviceTypeEnum.IOS.equals(userSoundInfoMap.get(phone).getDeviceType())&&bodyObject.containsKey(SoundSocketService.OFFSET_TIME)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    int offsetTime = bodyObject.getIntValue(SoundSocketService.OFFSET_TIME); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    calOffsetTime(phone, offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                if(DeviceTypeEnum.IOS.equals(userSoundInfoMap.get(phone).getDeviceType())&&bodyObject.containsKey(SoundSocketService.OFFSET_TIME)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                    int offsetTime = bodyObject.getIntValue(SoundSocketService.OFFSET_TIME); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                    calOffsetTime(phone, offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             case VIDEO_UPDATE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 SysMusicCompareRecord update = null; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -207,24 +211,27 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(!userSoundInfoMap.containsKey(phone)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        userSoundInfoMap.get(phone).setRecordBytes(userSoundInfoMap.get(phone).getRecordBytes()+message.getPayloadLength()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(userSoundInfoMap.get(phone).getRecordBytes()<userSoundInfoMap.get(phone).getFirstMeasureStartBytes()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 userSoundInfoMap.get(phone).getAccessFile().write(message.getPayload().array()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), soundCompareConfig.audioFormat, soundCompareConfig.simpleSize, soundCompareConfig.overlap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             dispatcher.addAudioProcessor(userSoundInfoMap.get(phone).silenceDetector); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             dispatcher.addAudioProcessor(new PitchProcessor(soundCompareConfig.algo, soundCompareConfig.simpleRate, soundCompareConfig.simpleSize, userSoundInfoMap.get(phone))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             dispatcher.run(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(Objects.isNull(userSoundInfoMap.get(phone).getAccessFile())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userSoundInfoMap.get(phone).setMeasureStartTime(recordTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             for (Map.Entry<Integer, MusicPitchDetailDto> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(recordTime>(userMeasureEndTimeMapEntry.getValue().getEndTimeStamp())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if(recordTime>(userMeasureEndTimeMapEntry.getValue().getEndTimeStamp()+100)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if(userMeasureEndTimeMapEntry.getValue().getDontEvaluating()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     }else{ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -261,6 +268,7 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             musicPitchDetailDtoEntry.getValue().setTimeStamp(musicPitchDetailDtoEntry.getValue().getTimeStamp() + offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             musicPitchDetailDtoEntry.getValue().setEndTimeStamp(musicPitchDetailDtoEntry.getValue().getEndTimeStamp() + offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        userSoundInfoMap.get(phone).getMusicXmlInfos().forEach(e->e.setTimeStamp(e.getTimeStamp()+offsetTime)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -347,111 +355,32 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             for (int i = 0; i < userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size(); i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 MusicPitchDetailDto musicXmlInfo = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).get(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                int ot5 = (int) (musicXmlInfo.getDuration()*0.1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                int startTimeStamp = musicXmlInfo.getTimeStamp() + userSoundInfoMap.get(phone).getOffsetTime() + ot5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                int endTimeStamp = musicXmlInfo.getTimeStamp()  + userSoundInfoMap.get(phone).getOffsetTime() + musicXmlInfo.getDuration() - ot5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //时间范围内有效节奏数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float cadenceValidNum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //时间范围内有效音频数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float integrityValidNum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //时间范围内匹配次数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float compareNum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int startTimeStamp = musicXmlInfo.getTimeStamp(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int endTimeStamp = musicXmlInfo.getTimeStamp() + musicXmlInfo.getDuration(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                List<MusicPitchDetailDto> measureSoundPitchInfos = new ArrayList<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int ot5 = (int) (musicXmlInfo.getDuration()*0.22<70?70:musicXmlInfo.getDuration()*0.22); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int rightTimeRange = ot5>200?200:ot5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                for (int j = 0; j < userSoundInfoMap.get(phone).getRecordMeasurePithInfo().size(); j++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    MusicPitchDetailDto recordInfo = userSoundInfoMap.get(phone).getRecordMeasurePithInfo().get(j); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //如果在时间范围之外直接跳过 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if(recordInfo.getTimeStamp()<startTimeStamp||recordInfo.getTimeStamp()>endTimeStamp){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    measureSoundPitchInfos.add(recordInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    compareNum++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //如果在最低有效频率以下则跳过 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if(recordInfo.getFrequency()<soundCompareConfig.validFrequency&&musicXmlInfo.getFrequency()!=-1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    cadenceValidNum++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //如果频率差值在节奏误差范围内 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=soundCompareConfig.integrityFrequencyRange){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                        integrityValidNum++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //非正常频率次数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                int errPitchNum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //分贝变化次数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                int decibelChangeNum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(CollectionUtils.isEmpty(measureSoundPitchInfos)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(musicXmlInfo.getMusicalNotesIndex(), (float) 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Map<Integer, Long> collect = measureSoundPitchInfos.stream().map(pitch -> (int)pitch.getFrequency()).collect(Collectors.groupingBy(Integer::intValue, Collectors.counting())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //出现次数最多的频率 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Integer pitch = collect.entrySet().stream().max(Comparator.comparing(e -> e.getValue())).get().getKey(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //当前频率 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double cf = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //频率持续数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    int fnum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //是否演奏中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    boolean ing = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //当前分贝 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double cd = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //分贝变化方向,-1变小,1变大 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    int dcd = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //分贝持续数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    int dnum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    for (MusicPitchDetailDto musicalNotesPitch : measureSoundPitchInfos) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        //计算频率断层次数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (Math.abs(musicalNotesPitch.getFrequency() - cf) > 20){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            fnum ++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (fnum>=5){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            cf = musicalNotesPitch.getFrequency(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            fnum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            if (cf != -1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                errPitchNum ++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                ing = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                cd = musicalNotesPitch.getDecibel(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        //计算声音大小断层册数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if(ing && Math.abs(musicalNotesPitch.getDecibel() - cd) > 10){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            dnum ++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (dnum > 2){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            int tdcd = cd > musicalNotesPitch.getDecibel() ? -1 : 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            cd = musicalNotesPitch.getDecibel(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            dnum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            if (tdcd != dcd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                decibelChangeNum++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            dcd = tdcd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(musicXmlInfo.getMusicalNotesIndex(), (float) pitch); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                List<MusicPitchDetailDto> recordPitchs = userSoundInfoMap.get(phone).getRecordMeasurePitchInfos().stream().filter(m -> m.getTimeStamp()>=startTimeStamp-rightTimeRange && m.getTimeStamp() < endTimeStamp-rightTimeRange).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 boolean cadenceRight = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 boolean intonationRight = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 boolean integrityRight = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //有效节奏占比 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float cadenceDuty = cadenceValidNum/compareNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //如果频率出现断层或这个音量出现断层,则当前音符节奏无效 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(errPitchNum>=2 || decibelChangeNum>1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    cadenceDuty = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                float integrityDuty = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if(recordPitchs.size()>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    integrityDuty = recordPitchs.get(0).getDuration()/(float)musicXmlInfo.getDuration(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                integrityDuty = scoreMapping(integrityDuty, userSoundInfoMap.get(phone).getHeardLevel().getIntegrityRange(), 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //节奏 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(cadenceDuty>=userSoundInfoMap.get(phone).getHeardLevel().getCadenceRange()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if(recordPitchs.size()==1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     cadenceNum++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     cadenceRight = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //音准、完成度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (cadenceRight && !CollectionUtils.isEmpty(measureSoundPitchInfos)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (cadenceRight){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     //音准 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Double avgPitch = measureSoundPitchInfos.stream().filter(pitch -> Math.abs((pitch.getFrequency()-musicXmlInfo.getFrequency()))<15).collect(Collectors.averagingDouble(pitch -> pitch.getFrequency())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    float avgPitch = recordPitchs.get(0).getFrequency(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     //音分 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     double recordCents = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (avgPitch > 0){ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -461,29 +390,40 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if(musicXmlInfo.getFrequency()>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         cents =  PitchConverter.hertzToAbsoluteCent(musicXmlInfo.getFrequency()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double score = 100 - Math.round(Math.abs(cents - recordCents)) + userSoundInfoMap.get(phone).getHeardLevel().getIntonationCentsRange(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    double score = 100 - Math.round(Math.abs(cents - recordCents)) + 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (score < 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         score = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     }else if(score > 100){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         score = 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    score = Math.pow(score/100f, userSoundInfoMap.get(phone).getHeardLevel().getIntonationCentsRange())*100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if(Objects.nonNull(userSoundInfoMap.get(phone).getSubjectId())&&userSoundInfoMap.get(phone).getSubjectId()==23){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        score = 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        integrityDuty = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     intonationScore += score; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    musicXmlInfo.setAvgFrequency(avgPitch.floatValue()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    musicXmlInfo.setAvgFrequency(avgPitch); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     intonationRight = score>70; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if(score>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        integrityValidNum = measureSoundPitchInfos.stream().filter(pitch -> Math.abs((pitch.getFrequency()-musicXmlInfo.getFrequency()))<15).count(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        integrityValidNum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    integrityScore += integrityDuty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    integrityRight = integrityDuty>0.7; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //完成度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(integrityValidNum > compareNum){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    integrityValidNum = compareNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //如果当前音符不需要演奏 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (musicXmlInfo.getFrequency()<0&&recordPitchs.size()<=0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    cadenceNum++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    cadenceRight = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    intonationScore += 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    musicXmlInfo.setAvgFrequency(-1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    intonationRight = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    integrityScore += 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    integrityRight = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float integrityDuty = integrityValidNum/compareNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                integrityScore += integrityDuty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                integrityRight = integrityDuty>0.7; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if(!cadenceRight){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     userSoundInfoMap.get(phone).getMusicalNotesPlayStats().add(new MusicalNotesPlayStatDto(musicXmlInfo.getMusicalNotesIndex(), MusicalErrorTypeEnum.CADENCE_WRONG)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -528,6 +468,11 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         createPushInfo(phone, "measureScore", measureIndex, intonation, cadence, integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private float scoreMapping(float score, float divisor, float maxValue){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        score = score*divisor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return score>maxValue?maxValue:score; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @describe 计算最终评分 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @author Joburgess 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -543,15 +488,15 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         BigDecimal integrity = BigDecimal.ZERO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(currentCompareNum>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            intonation = userSoundInfoMap.get(phone).getUserScoreMap().get("intonation").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            cadence = userSoundInfoMap.get(phone).getUserScoreMap().get("cadence").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            integrity = userSoundInfoMap.get(phone).getUserScoreMap().get("integrity").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            intonation = userSoundInfoMap.get(phone).getUserScoreMap().get("intonation").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            cadence = userSoundInfoMap.get(phone).getUserScoreMap().get("cadence").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            integrity = userSoundInfoMap.get(phone).getUserScoreMap().get("integrity").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //计算分数并推送 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         createPushInfo(phone, "overall", -1, intonation, cadence, integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone), SerializerFeature.DisableCircularReferenceDetect)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -570,12 +515,8 @@ public class SoundCompareHandler implements WebSocketEventHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         WebSocketInfo webSocketInfo = new WebSocketInfo(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         webSocketInfo.setHeader(new WebSocketInfo.Head(command)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Map<String, Object> result = new HashMap<>(5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //打击乐只看节奏分 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BigDecimal score = cadence; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //非打击乐总分为平均分 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(Objects.isNull(userSoundInfoMap.get(phone).getSubjectId())||userSoundInfoMap.get(phone).getSubjectId()!=23){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            score = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BigDecimal score  = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         result.put("score", score); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         result.put("intonation", intonation); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         result.put("cadence", cadence); 
			 |