|  | @@ -3,12 +3,11 @@ 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.dto.MusicPitchDetailDto;
 | 
	
		
			
				|  |  | -import com.ym.mec.biz.dal.dto.SoundCompareHelper;
 | 
	
		
			
				|  |  | -import com.ym.mec.biz.dal.dto.WavHeader;
 | 
	
		
			
				|  |  | -import com.ym.mec.biz.dal.dto.WebSocketInfo;
 | 
	
		
			
				|  |  | +import com.ym.mec.biz.dal.config.SoundCompareConfig;
 | 
	
		
			
				|  |  | +import com.ym.mec.biz.dal.dto.*;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.service.SoundSocketService;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.service.SysMusicCompareRecordService;
 | 
	
		
			
				|  |  |  import com.ym.mec.common.constant.CommonConstants;
 | 
	
	
		
			
				|  | @@ -21,7 +20,6 @@ import org.springframework.util.CollectionUtils;
 | 
	
		
			
				|  |  |  import org.springframework.web.socket.*;
 | 
	
		
			
				|  |  |  import org.springframework.web.socket.handler.AbstractWebSocketHandler;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -import javax.sound.sampled.AudioFormat;
 | 
	
		
			
				|  |  |  import java.io.File;
 | 
	
		
			
				|  |  |  import java.io.IOException;
 | 
	
		
			
				|  |  |  import java.io.RandomAccessFile;
 | 
	
	
		
			
				|  | @@ -41,24 +39,23 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    //存储客户端链接
 | 
	
		
			
				|  |  | -    public static final Map<String, WebSocketSession> WS_CLIENTS = new ConcurrentHashMap<>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    private final BigDecimal oneHundred = new BigDecimal(100);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    //检测偏移时长的最终时间
 | 
	
		
			
				|  |  | -    private final int endCheckOffsetTime = 500;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    private final float simpleRate = 44100;
 | 
	
		
			
				|  |  | -    private int simpleSize = 1024;
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * @describe 存储客户端链接
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static final Map<String, WebSocketClientDetail> WS_CLIENTS = new ConcurrentHashMap<>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private final AudioFormat audioFormat = new AudioFormat(simpleRate, 16, 1, true, false);
 | 
	
		
			
				|  |  | -    private static final PitchProcessor.PitchEstimationAlgorithm algo = PitchProcessor.PitchEstimationAlgorithm.FFT_YIN;
 | 
	
		
			
				|  |  | +    private BigDecimal oneHundred = new BigDecimal(100);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private static final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/";
 | 
	
		
			
				|  |  | +    private final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    //用户对应评分信息
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * @describe 用户对应评分信息
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  |      private Map<String, SoundCompareHelper> userSoundInfoMap = new ConcurrentHashMap<>();
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * @describe 音频处理参数
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private SoundCompareConfig soundCompareConfig = new SoundCompareConfig();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private SysMusicCompareRecordService sysMusicCompareRecordService;
 | 
	
	
		
			
				|  | @@ -75,7 +72,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |      public void afterConnectionEstablished(WebSocketSession session) throws Exception {
 | 
	
		
			
				|  |  |          String phone = session.getPrincipal().getName().split(":")[1];
 | 
	
		
			
				|  |  |          LOGGER.info("{}上线", phone);
 | 
	
		
			
				|  |  | -        WS_CLIENTS.put(phone, session);
 | 
	
		
			
				|  |  | +        WS_CLIENTS.put(phone, new WebSocketClientDetail(session, new Date()));
 | 
	
		
			
				|  |  |          super.afterConnectionEstablished(session);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -99,11 +96,19 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |              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 musicPitchDetailDto = userMeasureXmlInfoEntry.getValue().stream().max(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get();
 | 
	
		
			
				|  |  | -                    userSoundInfoMap.get(phone).getMeasureEndTime().put(userMeasureXmlInfoEntry.getKey(), musicPitchDetailDto.getTimeStamp()+musicPitchDetailDto.getDuration());
 | 
	
		
			
				|  |  | +                    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:
 | 
	
	
		
			
				|  | @@ -112,6 +117,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  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)){
 | 
	
	
		
			
				|  | @@ -119,9 +125,9 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  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()/(audioFormat.getFrameSize()*audioFormat.getFrameRate())*1000;
 | 
	
		
			
				|  |  | +                    double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
 | 
	
		
			
				|  |  |                      //如果结束时时长大于某小节,则此小节需要评分
 | 
	
		
			
				|  |  | -                    if(recordTime>userSoundInfoMap.get(phone).getMeasureEndTime().get(lastMeasureIndex)){
 | 
	
		
			
				|  |  | +                    if(recordTime>userSoundInfoMap.get(phone).getMeasureEndTime().get(lastMeasureIndex).getEndTimeStamp()){
 | 
	
		
			
				|  |  |                          measureCompare(phone, lastMeasureIndex);
 | 
	
		
			
				|  |  |                          userSoundInfoMap.get(phone).getMeasureEndTime().remove(lastMeasureIndex);
 | 
	
		
			
				|  |  |                      }
 | 
	
	
		
			
				|  | @@ -132,6 +138,12 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |              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;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -146,52 +158,36 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |          if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
 | 
	
		
			
				|  |  |              userSoundInfoMap.get(phone).getAccessFile().write(message.getPayload().array());
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        List<MusicPitchDetailDto> recordInfo = new ArrayList<>();
 | 
	
		
			
				|  |  | -        AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), audioFormat, simpleSize, 128);
 | 
	
		
			
				|  |  | -        dispatcher.addAudioProcessor(new PitchProcessor(algo, simpleRate, simpleSize, (pitchDetectionResult, audioEvent) -> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        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();
 | 
	
		
			
				|  |  | -//            LOGGER.info("频率:{}, {}", timeStamp, pitch);
 | 
	
		
			
				|  |  | -            recordInfo.add(new MusicPitchDetailDto(timeStamp, pitch));
 | 
	
		
			
				|  |  | +            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()/(audioFormat.getFrameSize()*audioFormat.getFrameRate())*1000;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
 | 
	
		
			
				|  |  |          userSoundInfoMap.get(phone).setMeasureStartTime(recordTime);
 | 
	
		
			
				|  |  | -        userSoundInfoMap.get(phone).getRecordMeasurePithInfo().addAll(recordInfo);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        //如果是第一小节,需要计算出录音与播放不同步导致的空白时间偏移量
 | 
	
		
			
				|  |  | -        if(userSoundInfoMap.get(phone).getOffsetTime()<=0&&recordTime<endCheckOffsetTime){
 | 
	
		
			
				|  |  | -            int hasPitchNum = 0;
 | 
	
		
			
				|  |  | -            for (MusicPitchDetailDto ri : userSoundInfoMap.get(phone).getRecordMeasurePithInfo()) {
 | 
	
		
			
				|  |  | -                if(hasPitchNum<=0){
 | 
	
		
			
				|  |  | -                    userSoundInfoMap.get(phone).setOffsetTime(ri.getTimeStamp());
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                if(ri.getFrequency()>0){
 | 
	
		
			
				|  |  | -                    hasPitchNum++;
 | 
	
		
			
				|  |  | +        for (Map.Entry<Integer, MusicPitchDetailDto> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
 | 
	
		
			
				|  |  | +            if(recordTime>(userMeasureEndTimeMapEntry.getValue().getEndTimeStamp())){
 | 
	
		
			
				|  |  | +                if(userMeasureEndTimeMapEntry.getValue().getDontEvaluating()){
 | 
	
		
			
				|  |  | +                    continue;
 | 
	
		
			
				|  |  |                  }else{
 | 
	
		
			
				|  |  | -                    hasPitchNum=0;
 | 
	
		
			
				|  |  | +                    measureCompare(phone, userMeasureEndTimeMapEntry.getKey());
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -                if(hasPitchNum>=3){
 | 
	
		
			
				|  |  | -                    LOGGER.info("偏移时间:{}", userSoundInfoMap.get(phone).getOffsetTime());
 | 
	
		
			
				|  |  | -                    break;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if(hasPitchNum<3){
 | 
	
		
			
				|  |  | -                userSoundInfoMap.get(phone).setOffsetTime(0);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if(userSoundInfoMap.get(phone).getOffsetTime()<=0&&recordTime<endCheckOffsetTime){
 | 
	
		
			
				|  |  | -            return;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        for (Map.Entry<Integer, Integer> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
 | 
	
		
			
				|  |  | -            if((recordTime - userSoundInfoMap.get(phone).getOffsetTime())>userMeasureEndTimeMapEntry.getValue()){
 | 
	
		
			
				|  |  | -                measureCompare(phone, userMeasureEndTimeMapEntry.getKey());
 | 
	
		
			
				|  |  |                  userSoundInfoMap.get(phone).getMeasureEndTime().remove(userMeasureEndTimeMapEntry.getKey());
 | 
	
		
			
				|  |  |                  break;
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -214,6 +210,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |          exception.printStackTrace();
 | 
	
		
			
				|  |  |          LOGGER.info("发生了错误,移除客户端: {}", phone);
 | 
	
		
			
				|  |  |          WS_CLIENTS.remove(phone);
 | 
	
		
			
				|  |  | +        userSoundInfoMap.remove(phone);
 | 
	
		
			
				|  |  |          createHeader(phone);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -222,8 +219,9 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |          super.afterConnectionClosed(session, status);
 | 
	
		
			
				|  |  |          String phone = session.getPrincipal().getName().split(":")[1];
 | 
	
		
			
				|  |  |          LOGGER.info("{}离线", phone);
 | 
	
		
			
				|  |  | -        WS_CLIENTS.remove(phone);
 | 
	
		
			
				|  |  |          createHeader(phone);
 | 
	
		
			
				|  |  | +        WS_CLIENTS.remove(phone);
 | 
	
		
			
				|  |  | +        userSoundInfoMap.remove(phone);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
	
		
			
				|  | @@ -232,6 +230,22 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | +     * @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
 | 
	
	
		
			
				|  | @@ -244,14 +258,13 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
 | 
	
		
			
				|  |  |              RandomAccessFile randomAccessFile = userSoundInfoMap.get(phone).getAccessFile();
 | 
	
		
			
				|  |  | -            LOGGER.info("音频时长:{}", randomAccessFile.length()/(audioFormat.getFrameSize()*audioFormat.getFrameRate())*1000);
 | 
	
		
			
				|  |  | +            LOGGER.info("音频时长:{}", randomAccessFile.length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000);
 | 
	
		
			
				|  |  |              randomAccessFile.seek(0);
 | 
	
		
			
				|  |  | -            randomAccessFile.write(WavHeader.getWaveHeader(randomAccessFile.length(), (long) audioFormat.getFrameRate(), audioFormat.getSampleSizeInBits()));
 | 
	
		
			
				|  |  | +            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);
 | 
	
		
			
				|  |  | -        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone)));
 | 
	
		
			
				|  |  |          userSoundInfoMap.remove(phone);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -264,6 +277,10 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |       * @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;
 | 
	
		
			
				|  |  |          //节奏
 | 
	
	
		
			
				|  | @@ -272,84 +289,151 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |          BigDecimal integrity = BigDecimal.ZERO;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  | -            //最低有效频率
 | 
	
		
			
				|  |  | -            float minValidFrequency = 20;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            //有效音频数量
 | 
	
		
			
				|  |  | -            float validNum = 0;
 | 
	
		
			
				|  |  | -            //音频有效阈值
 | 
	
		
			
				|  |  | -            float validDuty = 0.5f;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            //音准匹配数量
 | 
	
		
			
				|  |  | -            float intonationNum = 0;
 | 
	
		
			
				|  |  | -            //音准匹配误差范围
 | 
	
		
			
				|  |  | -            float intonationErrRange = 15;
 | 
	
		
			
				|  |  | -            //音准有效阈值
 | 
	
		
			
				|  |  | -            float intonationValidDuty = 0.7f;
 | 
	
		
			
				|  |  | +            //音准分数
 | 
	
		
			
				|  |  | +            float intonationScore = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              //节奏匹配数量
 | 
	
		
			
				|  |  |              float cadenceNum = 0;
 | 
	
		
			
				|  |  | -            //节奏匹配误差范围
 | 
	
		
			
				|  |  | -            float cadenceErrRange = 30;
 | 
	
		
			
				|  |  | -            //节奏有效阈值
 | 
	
		
			
				|  |  | -            float cadenceValidDuty = 0.6f;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //完整性分数
 | 
	
		
			
				|  |  | +            float integrityScore = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            for (MusicPitchDetailDto musicXmlInfo : userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex)) {
 | 
	
		
			
				|  |  | -                int startTimeStamp = musicXmlInfo.getTimeStamp() + userSoundInfoMap.get(phone).getOffsetTime();
 | 
	
		
			
				|  |  | -                int endTimeStamp = musicXmlInfo.getTimeStamp()+musicXmlInfo.getDuration() + userSoundInfoMap.get(phone).getOffsetTime();
 | 
	
		
			
				|  |  | +            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 recordValidIntonationNum = 0;
 | 
	
		
			
				|  |  |                  //时间范围内有效节奏数量
 | 
	
		
			
				|  |  |                  float cadenceValidNum = 0;
 | 
	
		
			
				|  |  |                  //时间范围内有效音频数量
 | 
	
		
			
				|  |  | -                float recordValidNum = 0;
 | 
	
		
			
				|  |  | +                float integrityValidNum = 0;
 | 
	
		
			
				|  |  |                  //时间范围内匹配次数
 | 
	
		
			
				|  |  |                  float compareNum = 0;
 | 
	
		
			
				|  |  | -                for (MusicPitchDetailDto recordInfo : userSoundInfoMap.get(phone).getRecordMeasurePithInfo()) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                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;
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -//                    LOGGER.info("{}频率({}-{}):{}, {}", recordInfo.getTimeStamp(), startTimeStamp, endTimeStamp, musicXmlInfo.getFrequency(), recordInfo.getFrequency());
 | 
	
		
			
				|  |  | +                    measureSoundPitchInfos.add(recordInfo);
 | 
	
		
			
				|  |  |                      compareNum++;
 | 
	
		
			
				|  |  |                      //如果在最低有效频率以下则跳过
 | 
	
		
			
				|  |  | -                    if(recordInfo.getFrequency()<minValidFrequency&&musicXmlInfo.getFrequency()!=-1){
 | 
	
		
			
				|  |  | +                    if(recordInfo.getFrequency()<soundCompareConfig.validFrequency&&musicXmlInfo.getFrequency()!=-1){
 | 
	
		
			
				|  |  |                          continue;
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                    recordValidNum++;
 | 
	
		
			
				|  |  | +                    cadenceValidNum++;
 | 
	
		
			
				|  |  |                      //如果频率差值在节奏误差范围内
 | 
	
		
			
				|  |  | -                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=cadenceErrRange){
 | 
	
		
			
				|  |  | -                        cadenceValidNum++;
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    //如果频率差值在音准误差范围内
 | 
	
		
			
				|  |  | -                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=intonationErrRange){
 | 
	
		
			
				|  |  | -                        recordValidIntonationNum++;
 | 
	
		
			
				|  |  | +                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=soundCompareConfig.integrityFrequencyRange){
 | 
	
		
			
				|  |  | +                        integrityValidNum++;
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -                //有效音频占比
 | 
	
		
			
				|  |  | -                float recordValidDuty = recordValidNum/compareNum;
 | 
	
		
			
				|  |  | -                if(recordValidDuty<validDuty){
 | 
	
		
			
				|  |  | -                    continue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                //非正常频率次数
 | 
	
		
			
				|  |  | +                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);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -                validNum++;
 | 
	
		
			
				|  |  | -                //有效音高占比
 | 
	
		
			
				|  |  | -                float intonationDuty = recordValidIntonationNum/compareNum;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                  //有效节奏占比
 | 
	
		
			
				|  |  |                  float cadenceDuty = cadenceValidNum/compareNum;
 | 
	
		
			
				|  |  | -                if(intonationDuty>=intonationValidDuty){
 | 
	
		
			
				|  |  | -                    intonationNum++;
 | 
	
		
			
				|  |  | +                //如果频率出现断层或这个音量出现断层,则当前音符节奏无效
 | 
	
		
			
				|  |  | +                if(errPitchNum>=2 || decibelChangeNum>1){
 | 
	
		
			
				|  |  | +                    cadenceDuty = 0;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -                if(cadenceDuty>=cadenceValidDuty){
 | 
	
		
			
				|  |  | +                //节奏
 | 
	
		
			
				|  |  | +                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;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            intonation = new BigDecimal(intonationNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_HALF_UP);
 | 
	
		
			
				|  |  | -            cadence = new BigDecimal(cadenceNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_HALF_UP);
 | 
	
		
			
				|  |  | -            integrity = new BigDecimal(validNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_HALF_UP);
 | 
	
		
			
				|  |  | +            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信息");
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -372,14 +456,8 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |              userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        Map<String, BigDecimal> scoreData = new HashMap<>();
 | 
	
		
			
				|  |  | -        scoreData.put("intonation", intonation);
 | 
	
		
			
				|  |  | -        scoreData.put("cadence", cadence);
 | 
	
		
			
				|  |  | -        scoreData.put("integrity", integrity);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        userSoundInfoMap.get(phone).getUserMeasureScoreMap().put(measureIndex, scoreData);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        WS_CLIENTS.get(phone).sendMessage(new TextMessage(JSON.toJSONString(createPushInfo("measureScore", measureIndex, intonation, cadence, integrity))));
 | 
	
		
			
				|  |  | +        //计算分数并推送
 | 
	
		
			
				|  |  | +        createPushInfo(phone, "measureScore", measureIndex, intonation, cadence, integrity);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
	
		
			
				|  | @@ -399,13 +477,16 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |          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 = new BigDecimal(currentCompareNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_DOWN);
 | 
	
		
			
				|  |  | +            integrity = userSoundInfoMap.get(phone).getUserScoreMap().get("integrity").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        WS_CLIENTS.get(phone).sendMessage(new TextMessage(JSON.toJSONString(createPushInfo("overall", -1, intonation, cadence, integrity))));
 | 
	
		
			
				|  |  | +        //计算分数并推送
 | 
	
		
			
				|  |  | +        createPushInfo(phone, "overall", -1, intonation, cadence, integrity);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          //存储评分数据
 | 
	
		
			
				|  |  | -        sysMusicCompareRecordService.saveMusicCompareData(phone, userSoundInfoMap.get(phone).getMusicScoreId(), userSoundInfoMap.get(phone).getUserMeasureScoreMap());
 | 
	
		
			
				|  |  | +        sysMusicCompareRecordService.saveMusicCompareData(phone, userSoundInfoMap.get(phone));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone)));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
	
		
			
				|  | @@ -419,22 +500,29 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 | 
	
		
			
				|  |  |       * @param integrity:
 | 
	
		
			
				|  |  |       * @return com.ym.mec.biz.dal.dto.WebSocketInfo
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    private WebSocketInfo createPushInfo(String command, Integer measureIndex,
 | 
	
		
			
				|  |  | -                                         BigDecimal intonation, BigDecimal cadence, BigDecimal integrity){
 | 
	
		
			
				|  |  | +    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 = cadence.setScale(0, BigDecimal.ROUND_HALF_UP);
 | 
	
		
			
				|  |  | +//        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;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |