| 
					
				 | 
			
			
				@@ -1,34 +1,20 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package com.ym.mec.biz.handler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import be.tarsos.dsp.AudioDispatcher; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import be.tarsos.dsp.io.jvm.AudioDispatcherFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import be.tarsos.dsp.pitch.PitchProcessor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import be.tarsos.dsp.util.PitchConverter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.alibaba.fastjson.JSON; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import com.alibaba.fastjson.JSONObject; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import com.ym.mec.biz.dal.config.SoundCompareConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import com.ym.mec.biz.dal.dto.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ym.mec.biz.dal.dto.WebSocketClientDetail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ym.mec.biz.dal.dto.WebSocketInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ym.mec.biz.service.SoundSocketService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import com.ym.mec.biz.service.SysMusicCompareRecordService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import com.ym.mec.common.constant.CommonConstants; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.apache.commons.io.FileUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ym.mec.biz.service.WebSocketEventHandler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.lang3.StringUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.slf4j.Logger; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.slf4j.LoggerFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.springframework.beans.factory.annotation.Autowired; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.stereotype.Service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.springframework.util.CollectionUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.web.socket.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.web.socket.handler.AbstractWebSocketHandler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.io.File; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.io.IOException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.io.RandomAccessFile; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.math.BigDecimal; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.time.LocalDateTime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.time.format.DateTimeFormatter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.util.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Date; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.concurrent.ConcurrentHashMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.util.stream.Collectors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * @Author Joburgess 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -37,35 +23,29 @@ import java.util.stream.Collectors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Service 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public class WebSocketHandler extends AbstractWebSocketHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @describe 存储客户端链接 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public static final Map<String, WebSocketClientDetail> WS_CLIENTS = new ConcurrentHashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private BigDecimal oneHundred = new BigDecimal(100); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private static Map<String, WebSocketEventHandler> appMap = new ConcurrentHashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @describe 用户对应评分信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private Map<String, SoundCompareHelper> userSoundInfoMap = new ConcurrentHashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @describe 音频处理参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @describe 注册应用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @author Joburgess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @date 2021/8/5 0005 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param tag: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param webSocketEventHandler: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return boolean 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private SoundCompareConfig soundCompareConfig = new SoundCompareConfig(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private SysMusicCompareRecordService sysMusicCompareRecordService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public WebSocketHandler() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        super(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        File soundDir = new File(tmpDir); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(!soundDir.exists()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            soundDir.mkdir(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static boolean regist(String tag, WebSocketEventHandler webSocketEventHandler){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (appMap.containsKey(tag)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        appMap.put(tag, webSocketEventHandler); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -73,6 +53,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String phone = session.getPrincipal().getName().split(":")[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LOGGER.info("{}上线", phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         WS_CLIENTS.put(phone, new WebSocketClientDetail(session, new Date())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        appMap.values().forEach(e->e.afterConnectionEstablished(session)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         super.afterConnectionEstablished(session); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -82,116 +63,24 @@ public class WebSocketHandler extends AbstractWebSocketHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected void handleTextMessage(WebSocketSession session, TextMessage message){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String phone = session.getPrincipal().getName().split(":")[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LOGGER.info("{}: {}", phone, message.getPayload()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         WebSocketInfo webSocketInfo = JSON.parseObject(message.getPayload(), WebSocketInfo.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        JSONObject bodyObject = (JSONObject) webSocketInfo.getBody(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String commond = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(webSocketInfo.getHeader().containsKey(SoundSocketService.COMMOND)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            commond = webSocketInfo.getHeader().get(SoundSocketService.COMMOND); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String tag = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(webSocketInfo.getHeader().containsKey(SoundSocketService.TAG)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            tag = webSocketInfo.getHeader().get(SoundSocketService.TAG); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        switch (commond){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            case SoundSocketService.MUSIC_XML: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userSoundInfoMap.put(phone, new SoundCompareHelper()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                List<MusicPitchDetailDto> musicXmlInfos = JSON.parseArray(bodyObject.getString("musicXmlInfos"), MusicPitchDetailDto.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userSoundInfoMap.get(phone).setMusicXmlInfos(musicXmlInfos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                musicXmlInfos = musicXmlInfos.stream().filter(m->!m.getDontEvaluating()).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userSoundInfoMap.get(phone).setMusicScoreId(bodyObject.getInteger("id")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userSoundInfoMap.get(phone).setMeasureXmlInfoMap(musicXmlInfos.stream().collect(Collectors.groupingBy(MusicPitchDetailDto::getMeasureIndex))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                musicXmlInfos.forEach(e->userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(e.getMusicalNotesIndex(), e.getFrequency())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                for (Map.Entry<Integer, List<MusicPitchDetailDto>> userMeasureXmlInfoEntry : userSoundInfoMap.get(phone).getMeasureXmlInfoMap().entrySet()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    MusicPitchDetailDto firstPitch = userMeasureXmlInfoEntry.getValue().stream().min(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    MusicPitchDetailDto lastPitch = userMeasureXmlInfoEntry.getValue().stream().max(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    long dc = userMeasureXmlInfoEntry.getValue().stream().filter(m -> m.getDontEvaluating()).count(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    MusicPitchDetailDto musicPitchDetailDto = new MusicPitchDetailDto(firstPitch.getTimeStamp(), lastPitch.getTimeStamp() + lastPitch.getDuration()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    musicPitchDetailDto.setDuration(musicPitchDetailDto.getEndTimeStamp()-musicPitchDetailDto.getTimeStamp()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    musicPitchDetailDto.setDontEvaluating(dc == userMeasureXmlInfoEntry.getValue().size()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    userSoundInfoMap.get(phone).getMeasureEndTime().put(userMeasureXmlInfoEntry.getKey(), musicPitchDetailDto); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            case SoundSocketService.RECORD_START: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(!userSoundInfoMap.containsKey(phone)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                File file = new File(tmpDir+phone + "_"+ userSoundInfoMap.get(phone).getMusicScoreId() +"_"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +".wav"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userSoundInfoMap.get(phone).setAccessFile(new RandomAccessFile(file, "rw")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userSoundInfoMap.get(phone).setRecordFilePath(file.getAbsolutePath()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            case SoundSocketService.RECORD_END: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(!userSoundInfoMap.containsKey(phone)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(!CollectionUtils.isEmpty(userSoundInfoMap.get(phone).getMeasureEndTime())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Integer lastMeasureIndex = userSoundInfoMap.get(phone).getMeasureEndTime().keySet().stream().min(Integer::compareTo).get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //如果结束时时长大于某小节,则此小节需要评分 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if(recordTime>userSoundInfoMap.get(phone).getMeasureEndTime().get(lastMeasureIndex).getEndTimeStamp()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        measureCompare(phone, lastMeasureIndex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        userSoundInfoMap.get(phone).getMeasureEndTime().remove(lastMeasureIndex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calTotalScore(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                createHeader(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            case SoundSocketService.RECORD_CANCEL: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                createHeader(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            case SoundSocketService.PROXY_MESSAGE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                if(bodyObject.containsKey(SoundSocketService.OFFSET_TIME)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                    int offsetTime = bodyObject.getIntValue(SoundSocketService.OFFSET_TIME); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                    calOffsetTime(phone, offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(StringUtils.isNotBlank(tag)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            appMap.get(tag).receiveTextMessage(session, message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            appMap.values().forEach(e->e.receiveTextMessage(session, message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String phone = session.getPrincipal().getName().split(":")[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(!userSoundInfoMap.containsKey(phone)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getAccessFile().write(message.getPayload().array()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        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, (pitchDetectionResult, audioEvent) -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            int timeStamp = (int) (userSoundInfoMap.get(phone).getMeasureStartTime() + audioEvent.getTimeStamp()*1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            float pitch = pitchDetectionResult.getPitch(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(pitch>0 && userSoundInfoMap.get(phone).getOffsetTime() == -1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                int preTimeStamp = CollectionUtils.isEmpty(userSoundInfoMap.get(phone).getRecordMeasurePithInfo())?0:userSoundInfoMap.get(phone).getRecordMeasurePithInfo().get(userSoundInfoMap.get(phone).getRecordMeasurePithInfo().size()-1).getTimeStamp(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calOffsetTime(phone, timeStamp - (timeStamp - preTimeStamp)/2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(userSoundInfoMap.get(phone).silenceDetector.currentSPL()<soundCompareConfig.validDb){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                pitch = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//            LOGGER.info("时间:{}, 频率:{}, 分贝:{}", timeStamp, pitch, silenceDetecor.currentSPL()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getRecordMeasurePithInfo().add(new MusicPitchDetailDto(timeStamp, pitch, userSoundInfoMap.get(phone).silenceDetector.currentSPL())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        })); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        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(userMeasureEndTimeMapEntry.getValue().getDontEvaluating()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    measureCompare(phone, userMeasureEndTimeMapEntry.getKey()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userSoundInfoMap.get(phone).getMeasureEndTime().remove(userMeasureEndTimeMapEntry.getKey()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        appMap.values().forEach(e->e.receiveBinaryMessage(session, message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -204,14 +93,13 @@ public class WebSocketHandler extends AbstractWebSocketHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String phone = session.getPrincipal().getName().split(":")[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         session.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        LOGGER.info("发生了错误,移除客户端: {}", phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        appMap.values().forEach(e->e.afterConnectionClosed(session)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exception.printStackTrace(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(!WS_CLIENTS.containsKey(phone)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        exception.printStackTrace(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        LOGGER.info("发生了错误,移除客户端: {}", phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         WS_CLIENTS.remove(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        userSoundInfoMap.remove(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        createHeader(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -219,310 +107,12 @@ public class WebSocketHandler extends AbstractWebSocketHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         super.afterConnectionClosed(session, status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String phone = session.getPrincipal().getName().split(":")[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LOGGER.info("{}离线", phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        createHeader(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        appMap.values().forEach(e->e.afterConnectionClosed(session)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         WS_CLIENTS.remove(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        userSoundInfoMap.remove(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public boolean supportsPartialMessages() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return super.supportsPartialMessages(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @describe 处理时间偏移 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @author Joburgess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @date 2021/7/5 0005 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param phone: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param offsetTime: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @return void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private void calOffsetTime(String phone, int offsetTime){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        userSoundInfoMap.get(phone).setOffsetTime(offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (Map.Entry<Integer, MusicPitchDetailDto> musicPitchDetailDtoEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            musicPitchDetailDtoEntry.getValue().setTimeStamp(musicPitchDetailDtoEntry.getValue().getTimeStamp() + offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            musicPitchDetailDtoEntry.getValue().setEndTimeStamp(musicPitchDetailDtoEntry.getValue().getEndTimeStamp() + offsetTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @describe 保存录音数据,并生成wav头信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @author Joburgess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @date 2021/6/25 0025 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param phone: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @return void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private void createHeader(String phone) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(!userSoundInfoMap.containsKey(phone)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            RandomAccessFile randomAccessFile = userSoundInfoMap.get(phone).getAccessFile(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            LOGGER.info("音频时长:{}", randomAccessFile.length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            randomAccessFile.seek(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            randomAccessFile.write(WavHeader.getWaveHeader(randomAccessFile.length(), (long) soundCompareConfig.audioFormat.getFrameRate(), soundCompareConfig.audioFormat.getSampleSizeInBits())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            randomAccessFile.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).setAccessFile(null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        userSoundInfoMap.get(phone).setRecordMeasurePithInfo(null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        userSoundInfoMap.remove(phone); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @describe 数据比对,生成分数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @author Joburgess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @date 2021/6/25 0025 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param phone: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param measureIndex: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @return void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private void measureCompare(String phone, int measureIndex) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (userSoundInfoMap.get(phone).getOffsetTime() == -1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).setOffsetTime(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //相似度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BigDecimal intonation = BigDecimal.ZERO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //节奏 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BigDecimal cadence = BigDecimal.ZERO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //完整度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BigDecimal integrity = BigDecimal.ZERO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //音准分数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            float intonationScore = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //节奏匹配数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            float cadenceNum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //完整性分数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            float integrityScore = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                List<MusicPitchDetailDto> measureSoundPitchInfos = new ArrayList<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //有效节奏占比 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float cadenceDuty = cadenceValidNum/compareNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //如果频率出现断层或这个音量出现断层,则当前音符节奏无效 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(errPitchNum>=2 || decibelChangeNum>1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    cadenceDuty = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //节奏 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(cadenceDuty>=soundCompareConfig.cadenceValidDuty){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    cadenceNum++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //音准 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!CollectionUtils.isEmpty(measureSoundPitchInfos)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Double avgPitch = measureSoundPitchInfos.stream().filter(pitch -> Math.abs((pitch.getFrequency()-musicXmlInfo.getFrequency()))<5).collect(Collectors.averagingDouble(pitch -> pitch.getFrequency())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //音分 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double recordCents = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (avgPitch > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        recordCents = PitchConverter.hertzToAbsoluteCent(avgPitch); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double cents = PitchConverter.hertzToAbsoluteCent(musicXmlInfo.getFrequency()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double score = 100 - Math.round(Math.abs(cents - recordCents)) + soundCompareConfig.intonationCentsRange; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (score < 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        score = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    }else if(score > 100){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        score = 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    intonationScore += score; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    musicXmlInfo.setAvgFrequency(avgPitch.floatValue()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //完成度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(integrityValidNum>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    integrityValidNum = integrityValidNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(integrityValidNum > compareNum){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    integrityValidNum = compareNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float integrityDuty = integrityValidNum/compareNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                integrityScore += integrityDuty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            BigDecimal measureNum = new BigDecimal(totalCompareNum); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            intonation = new BigDecimal(intonationScore).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            cadence = new BigDecimal(cadenceNum).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            integrity = new BigDecimal(integrityScore).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } catch (ArithmeticException e){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            LOGGER.info("无musicXml信息"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("intonation")){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getUserScoreMap().put("intonation", intonation.add(userSoundInfoMap.get(phone).getUserScoreMap().get("intonation"))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getUserScoreMap().put("intonation", intonation); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("cadence")){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getUserScoreMap().put("cadence", cadence.add(userSoundInfoMap.get(phone).getUserScoreMap().get("cadence"))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getUserScoreMap().put("cadence", cadence); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("integrity")){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity.add(userSoundInfoMap.get(phone).getUserScoreMap().get("integrity"))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //计算分数并推送 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        createPushInfo(phone, "measureScore", measureIndex, intonation, cadence, integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @describe 计算最终评分 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @author Joburgess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @date 2021/6/25 0025 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param phone: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @return void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private void calTotalScore(String phone) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().keySet().size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        int currentCompareNum = totalCompareNum-userSoundInfoMap.get(phone).getMeasureEndTime().keySet().size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BigDecimal intonation = BigDecimal.ZERO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BigDecimal cadence = BigDecimal.ZERO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //计算分数并推送 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        createPushInfo(phone, "overall", -1, intonation, cadence, integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //存储评分数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sysMusicCompareRecordService.saveMusicCompareData(phone, userSoundInfoMap.get(phone)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @describe 生成评分结果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @author Joburgess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @date 2021/6/25 0025 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param command: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param measureIndex: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param intonation: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param cadence: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param integrity: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @return com.ym.mec.biz.dal.dto.WebSocketInfo 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private WebSocketInfo createPushInfo(String phone, String command, Integer measureIndex, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                         BigDecimal intonation, BigDecimal cadence, BigDecimal integrity) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        WebSocketInfo webSocketInfo = new WebSocketInfo(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        HashMap<String, String> header = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        header.put("commond", command); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        webSocketInfo.setHeader(header); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Map<String, Object> result = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        BigDecimal score = intonation.multiply(new BigDecimal(0.5)).add(cadence.multiply(new BigDecimal(0.5))).setScale(0, BigDecimal.ROUND_HALF_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BigDecimal score = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        BigDecimal score = integrity.setScale(0, BigDecimal.ROUND_HALF_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        result.put("score", score); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        result.put("intonation", intonation); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        result.put("cadence", cadence); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        result.put("integrity", integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        result.put("measureIndex", measureIndex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        webSocketInfo.setBody(result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        userSoundInfoMap.get(phone).getUserMeasureScoreMap().put(measureIndex, result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        LOGGER.info("小节频分:{}", JSON.toJSONString(webSocketInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //推送结果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        WS_CLIENTS.get(phone).getSession().sendMessage(new TextMessage(JSON.toJSONString(webSocketInfo))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return webSocketInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |