Explorar o código

Merge branch 'music_score' into online1

Joburgess %!s(int64=4) %!d(string=hai) anos
pai
achega
bdba44fdf4

+ 60 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/config/SoundCompareConfig.java

@@ -0,0 +1,60 @@
+package com.ym.mec.biz.dal.config;
+
+import be.tarsos.dsp.SilenceDetector;
+import be.tarsos.dsp.pitch.PitchProcessor;
+
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/4 0004
+ */
+public class SoundCompareConfig {
+
+    /**
+     * @describe 采样率
+     */
+    public float simpleRate = 44100;
+    /**
+     * @describe 采样大小
+     */
+    public int simpleSize = 1024;
+    /**
+     * @describe 帧覆盖大小
+     */
+    public int overlap = 256;
+
+    /**
+     * @describe 音频解析格式
+     */
+    public AudioFormat audioFormat = new AudioFormat(simpleRate, 16, 1, true, false);
+    /**
+     * @describe 音频解析算法
+     */
+    public PitchProcessor.PitchEstimationAlgorithm algo = PitchProcessor.PitchEstimationAlgorithm.FFT_YIN;
+    /**
+     * @describe 分贝检测器
+     */
+    public SilenceDetector silenceDetector = new SilenceDetector();
+
+    /**
+     * @describe 有效分贝大小
+     */
+    public int validDb = -70;
+    /**
+     * @describe 有效频率
+     */
+    public int validFrequency = 20;
+    /**
+     * @describe 音准前后音分误差范围
+     */
+    public int intonationCentsRange = 3;
+    /**
+     * @describe 节奏有效阈值
+     */
+    public float cadenceValidDuty = 0.09f;
+    /**
+     * @describe 完整性有效频率误差范围
+     */
+    public int integrityFrequencyRange = 30;
+}

+ 65 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicPitchDetailDto.java

@@ -11,15 +11,69 @@ public class MusicPitchDetailDto {
     @ApiModelProperty("时间戳ms")
     private int timeStamp;
 
+    @ApiModelProperty("结束时间戳")
+    private int endTimeStamp;
+
     @ApiModelProperty("持续时长ms")
     private int duration;
 
     @ApiModelProperty("频率Hz")
     private float frequency;
 
+    private float avgFrequency;
+
+    @ApiModelProperty("分贝")
+    private float decibel;
+
     @ApiModelProperty("小节数")
     private int measureIndex;
 
+    @ApiModelProperty("音符数")
+    private int musicalNotesIndex;
+
+    @ApiModelProperty("不需要评分")
+    private Boolean dontEvaluating;
+
+    public float getDecibel() {
+        return decibel;
+    }
+
+    public void setDecibel(float decibel) {
+        this.decibel = decibel;
+    }
+
+    public float getAvgFrequency() {
+        return avgFrequency;
+    }
+
+    public void setAvgFrequency(float avgFrequency) {
+        this.avgFrequency = avgFrequency;
+    }
+
+    public Boolean getDontEvaluating() {
+        return dontEvaluating;
+    }
+
+    public void setDontEvaluating(Boolean dontEvaluating) {
+        this.dontEvaluating = dontEvaluating;
+    }
+
+    public int getMusicalNotesIndex() {
+        return musicalNotesIndex;
+    }
+
+    public void setMusicalNotesIndex(int musicalNotesIndex) {
+        this.musicalNotesIndex = musicalNotesIndex;
+    }
+
+    public int getEndTimeStamp() {
+        return endTimeStamp;
+    }
+
+    public void setEndTimeStamp(int endTimeStamp) {
+        this.endTimeStamp = endTimeStamp;
+    }
+
     public MusicPitchDetailDto() {
     }
 
@@ -28,12 +82,23 @@ public class MusicPitchDetailDto {
         this.frequency = frequency;
     }
 
+    public MusicPitchDetailDto(int timeStamp, int endTimeStamp) {
+        this.timeStamp = timeStamp;
+        this.endTimeStamp = endTimeStamp;
+    }
+
     public MusicPitchDetailDto(int timeStamp, int duration, float frequency) {
         this.timeStamp = timeStamp;
         this.duration = duration;
         this.frequency = frequency;
     }
 
+    public MusicPitchDetailDto(int timeStamp, float frequency, double decibel) {
+        this.timeStamp = timeStamp;
+        this.frequency = frequency;
+        this.decibel = (float) decibel;
+    }
+
     public int getTimeStamp() {
         return timeStamp;
     }

+ 50 - 8
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/SoundCompareHelper.java

@@ -16,16 +16,19 @@ public class SoundCompareHelper {
     private Integer musicScoreId;
 
     @ApiModelProperty(value = "小节开始时间")
-    private double measureStartTime;
+    private double measureStartTime = 0;
 
     @ApiModelProperty
     private RandomAccessFile accessFile;
 
+    @ApiModelProperty(value = "录音文件地址")
+    private String recordFilePath;
+
     @ApiModelProperty(value = "小节xml信息字典")
     private Map<Integer, List<MusicPitchDetailDto>> measureXmlInfoMap = new HashMap<>();
 
     @ApiModelProperty(value = "小节结束时间字典")
-    private Map<Integer, Integer> measureEndTime = new HashMap<>();
+    private Map<Integer, MusicPitchDetailDto> measureEndTime = new HashMap<>();
 
     @ApiModelProperty(value = "录音音频信息")
     private List<MusicPitchDetailDto> recordMeasurePithInfo = new ArrayList<>();
@@ -33,10 +36,41 @@ public class SoundCompareHelper {
     @ApiModelProperty(value = "小节分数记录")
     private Map<String, BigDecimal> userScoreMap = new HashMap<>();
 
-    private Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap = new HashMap<>();
+    private Map<Integer, Map<String, Object>> userMeasureScoreMap = new HashMap<>();
+
+    @ApiModelProperty(value = "音符频率字典")
+    private Map<Integer, Float> musicalNotePitchMap = new HashMap<>();
 
     @ApiModelProperty(value = "偏移时间量,解决客户端录音播放不同步导致的声音留白")
-    private int offsetTime;
+    private int offsetTime = -1;
+
+    private List<MusicPitchDetailDto> musicXmlInfos;
+
+    private byte[] preDataArray = new byte[0];
+
+    public List<MusicPitchDetailDto> getMusicXmlInfos() {
+        return musicXmlInfos;
+    }
+
+    public void setMusicXmlInfos(List<MusicPitchDetailDto> musicXmlInfos) {
+        this.musicXmlInfos = musicXmlInfos;
+    }
+
+    public Map<Integer, Float> getMusicalNotePitchMap() {
+        return musicalNotePitchMap;
+    }
+
+    public void setMusicalNotePitchMap(Map<Integer, Float> musicalNotePitchMap) {
+        this.musicalNotePitchMap = musicalNotePitchMap;
+    }
+
+    public byte[] getPreDataArray() {
+        return preDataArray;
+    }
+
+    public void setPreDataArray(byte[] preDataArray) {
+        this.preDataArray = preDataArray;
+    }
 
     public int getOffsetTime() {
         return offsetTime;
@@ -58,6 +92,14 @@ public class SoundCompareHelper {
         return accessFile;
     }
 
+    public String getRecordFilePath() {
+        return recordFilePath;
+    }
+
+    public void setRecordFilePath(String recordFilePath) {
+        this.recordFilePath = recordFilePath;
+    }
+
     public void setAccessFile(RandomAccessFile accessFile) {
         this.accessFile = accessFile;
     }
@@ -78,11 +120,11 @@ public class SoundCompareHelper {
         this.measureXmlInfoMap = measureXmlInfoMap;
     }
 
-    public Map<Integer, Integer> getMeasureEndTime() {
+    public Map<Integer, MusicPitchDetailDto> getMeasureEndTime() {
         return measureEndTime;
     }
 
-    public void setMeasureEndTime(Map<Integer, Integer> measureEndTime) {
+    public void setMeasureEndTime(Map<Integer, MusicPitchDetailDto> measureEndTime) {
         this.measureEndTime = measureEndTime;
     }
 
@@ -102,11 +144,11 @@ public class SoundCompareHelper {
         this.userScoreMap = userScoreMap;
     }
 
-    public Map<Integer, Map<String, BigDecimal>> getUserMeasureScoreMap() {
+    public Map<Integer, Map<String, Object>> getUserMeasureScoreMap() {
         return userMeasureScoreMap;
     }
 
-    public void setUserMeasureScoreMap(Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap) {
+    public void setUserMeasureScoreMap(Map<Integer, Map<String, Object>> userMeasureScoreMap) {
         this.userMeasureScoreMap = userMeasureScoreMap;
     }
 }

+ 53 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/WebSocketClientDetail.java

@@ -0,0 +1,53 @@
+package com.ym.mec.biz.dal.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.springframework.web.socket.WebSocketSession;
+
+import java.util.Date;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/4 0004
+ */
+public class WebSocketClientDetail {
+
+    private WebSocketSession session;
+
+    @ApiModelProperty(value = "用户登录时间")
+    private Date loginTime;
+
+    @ApiModelProperty(value = "用户退出或断开时间")
+    private Date logoutTime;
+
+    public WebSocketClientDetail() {
+    }
+
+    public WebSocketClientDetail(WebSocketSession session, Date loginTime) {
+        this.session = session;
+        this.loginTime = loginTime;
+    }
+
+    public WebSocketSession getSession() {
+        return session;
+    }
+
+    public void setSession(WebSocketSession session) {
+        this.session = session;
+    }
+
+    public Date getLoginTime() {
+        return loginTime;
+    }
+
+    public void setLoginTime(Date loginTime) {
+        this.loginTime = loginTime;
+    }
+
+    public Date getLogoutTime() {
+        return logoutTime;
+    }
+
+    public void setLogoutTime(Date logoutTime) {
+        this.logoutTime = logoutTime;
+    }
+}

+ 58 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicCompareRecord.java

@@ -2,6 +2,8 @@ package com.ym.mec.biz.dal.entity;
 
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
+import java.math.BigDecimal;
+
 /**
  * 对应数据库表(sys_music_compare_record):
  */
@@ -18,6 +20,21 @@ public class SysMusicCompareRecord {
 	
 	/** 评分数据 */
 	private String scoreData;
+
+	/** 总分 */
+	private BigDecimal score;
+
+	/** 音准 */
+	private BigDecimal intonation;
+
+	/** 节奏 */
+	private BigDecimal cadence;
+
+	/** 完成度 */
+	private BigDecimal integrity;
+
+	/** 录音文件地址 */
+	private String recordFilePath;
 	
 	/** 创建时间 */
 	private java.util.Date createTime;
@@ -53,7 +70,47 @@ public class SysMusicCompareRecord {
 	public String getScoreData(){
 		return this.scoreData;
 	}
-			
+
+	public BigDecimal getScore() {
+		return score;
+	}
+
+	public void setScore(BigDecimal score) {
+		this.score = score;
+	}
+
+	public BigDecimal getIntonation() {
+		return intonation;
+	}
+
+	public void setIntonation(BigDecimal intonation) {
+		this.intonation = intonation;
+	}
+
+	public BigDecimal getCadence() {
+		return cadence;
+	}
+
+	public void setCadence(BigDecimal cadence) {
+		this.cadence = cadence;
+	}
+
+	public BigDecimal getIntegrity() {
+		return integrity;
+	}
+
+	public void setIntegrity(BigDecimal integrity) {
+		this.integrity = integrity;
+	}
+
+	public String getRecordFilePath() {
+		return recordFilePath;
+	}
+
+	public void setRecordFilePath(String recordFilePath) {
+		this.recordFilePath = recordFilePath;
+	}
+
 	public void setCreateTime(java.util.Date createTime){
 		this.createTime = createTime;
 	}

+ 213 - 125
mec-biz/src/main/java/com/ym/mec/biz/handler/WebSocketHandler.java

@@ -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(soundCompareConfig.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(soundCompareConfig.silenceDetector.currentSPL()<soundCompareConfig.validDb){
+                pitch = -1;
+            }
+//            LOGGER.info("时间:{}, 频率:{}, 分贝:{}", timeStamp, pitch, silenceDetecor.currentSPL());
+            userSoundInfoMap.get(phone).getRecordMeasurePithInfo().add(new MusicPitchDetailDto(timeStamp, pitch, soundCompareConfig.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;
     }
 }

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/SoundSocketService.java

@@ -11,5 +11,7 @@ public interface SoundSocketService {
     String RECORD_START = "recordStart";
     String RECORD_END = "recordEnd";
     String RECORD_CANCEL = "recordCancel";
+    String PROXY_MESSAGE = "proxyMessage";
+    String OFFSET_TIME = "offsetTime";
 
 }

+ 3 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/SysMusicCompareRecordService.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.service;
 
+import com.ym.mec.biz.dal.dto.SoundCompareHelper;
 import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
 import com.ym.mec.common.service.BaseService;
 
@@ -13,9 +14,9 @@ public interface SysMusicCompareRecordService extends BaseService<Long, SysMusic
      * @author Joburgess
      * @date 2021/6/25 0025
      * @param phone:
-     * @param userMeasureScoreMap:
+     * @param soundCompareInfo:
      * @return void
      */
-    void saveMusicCompareData(String phone, Integer sysMusicScoreId, Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap);
+    void saveMusicCompareData(String phone, SoundCompareHelper soundCompareInfo);
 
 }

+ 12 - 3
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java

@@ -3,6 +3,7 @@ package com.ym.mec.biz.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.TeacherDao;
+import com.ym.mec.biz.dal.dto.SoundCompareHelper;
 import com.ym.mec.common.dal.BaseDAO;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
@@ -29,15 +30,23 @@ public class SysMusicCompareRecordServiceImpl extends BaseServiceImpl<Long, SysM
 	}
 
 	@Override
-	public void saveMusicCompareData(String phone, Integer sysMusicScoreId, Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap) {
+	public void saveMusicCompareData(String phone, SoundCompareHelper soundCompareInfo) {
 		SysUser user = teacherDao.getUserWithPhone(phone);
 		if(Objects.isNull(user)){
 			return;
 		}
 		SysMusicCompareRecord sysMusicCompareRecord = new SysMusicCompareRecord();
 		sysMusicCompareRecord.setUserId(user.getId());
-		sysMusicCompareRecord.setSysMusicScoreId(sysMusicScoreId);
-		sysMusicCompareRecord.setScoreData(JSON.toJSONString(userMeasureScoreMap));
+		sysMusicCompareRecord.setSysMusicScoreId(soundCompareInfo.getMusicScoreId());
+		sysMusicCompareRecord.setScoreData(JSON.toJSONString(soundCompareInfo.getUserMeasureScoreMap()));
+		if (Objects.nonNull(soundCompareInfo.getUserMeasureScoreMap()) && soundCompareInfo.getUserMeasureScoreMap().containsKey(-1)){
+			Map<String, Object> finalScore = soundCompareInfo.getUserMeasureScoreMap().get(-1);
+			sysMusicCompareRecord.setScore((BigDecimal) finalScore.get("score"));
+			sysMusicCompareRecord.setIntonation((BigDecimal) finalScore.get("intonation"));
+			sysMusicCompareRecord.setCadence((BigDecimal) finalScore.get("cadence"));
+			sysMusicCompareRecord.setIntegrity((BigDecimal) finalScore.get("integrity"));
+		}
+		sysMusicCompareRecord.setRecordFilePath(soundCompareInfo.getRecordFilePath());
 		sysMusicCompareRecordDao.insert(sysMusicCompareRecord);
 	}
 }

+ 22 - 2
mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml

@@ -11,6 +11,11 @@
 		<result column="user_id_" property="userId" />
 		<result column="sys_music_score_id_" property="sysMusicScoreId" />
 		<result column="score_data_" property="scoreData" />
+		<result column="score_" property="score" />
+		<result column="intonation_" property="intonation" />
+		<result column="cadence_" property="cadence" />
+		<result column="integrity_" property="integrity" />
+		<result column="record_file_path_" property="recordFilePath" />
 		<result column="create_time_" property="createTime" />
 	</resultMap>
 
@@ -31,8 +36,8 @@
 		SELECT SEQ_WSDEFINITION_ID.nextval AS ID FROM DUAL 
 		</selectKey>
 		-->
-		INSERT INTO sys_music_compare_record (id_,user_id_,sys_music_score_id_,score_data_,create_time_)
-		VALUES(#{id},#{userId},#{sysMusicScoreId},#{scoreData},NOW())
+		INSERT INTO sys_music_compare_record (id_,user_id_,sys_music_score_id_,score_data_,score_,intonation_,cadence_,integrity_,record_file_path_,create_time_)
+		VALUES(#{id},#{userId},#{sysMusicScoreId},#{scoreData},#{score},#{intonation},#{cadence},#{integrity},#{recordFilePath},NOW())
 	</insert>
 
 	<!-- 根据主键查询一条记录 -->
@@ -50,6 +55,21 @@
 		<if test="scoreData != null">
 			score_data_ = #{scoreData},
 		</if>
+		<if test="score != null">
+			score_ = #{score},
+		</if>
+		<if test="integrity != null">
+			integrity_ = #{integrity},
+		</if>
+		<if test="cadence != null">
+			cadence_ = #{cadence},
+		</if>
+		<if test="sysMusicScoreId != null">
+			sys_music_score_id_ = #{sysMusicScoreId},
+		</if>
+		<if test="recordFilePath != null">
+			record_file_path_ = #{recordFilePath},
+		</if>
 		<if test="createTime != null">
 			create_time_ = #{createTime},
 		</if>

+ 3 - 2
mec-student/src/main/java/com/ym/mec/student/config/WebSocketConfig.java

@@ -25,8 +25,9 @@ public class WebSocketConfig implements WebSocketConfigurer {
 
     @Override
     public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
-        webSocketHandlerRegistry.addHandler(webSocketHandler, "/ws")
-                .addInterceptors(webSocketHandshakeInterceptor);
+        webSocketHandlerRegistry.addHandler(webSocketHandler, "/audioEvaluate")
+                .addInterceptors(webSocketHandshakeInterceptor)
+                .setAllowedOrigins("*");
     }
 
     @Bean

+ 3 - 2
mec-teacher/src/main/java/com/ym/mec/teacher/config/WebSocketConfig.java

@@ -25,8 +25,9 @@ public class WebSocketConfig implements WebSocketConfigurer {
 
     @Override
     public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
-        webSocketHandlerRegistry.addHandler(webSocketHandler, "/ws")
-                .addInterceptors(webSocketHandshakeInterceptor);
+        webSocketHandlerRegistry.addHandler(webSocketHandler, "/audioEvaluate", "/ws")
+                .addInterceptors(webSocketHandshakeInterceptor)
+                .setAllowedOrigins("*");
     }
 
     @Bean

+ 4 - 4
mec-teacher/src/main/java/com/ym/mec/teacher/controller/SoundController.java

@@ -54,10 +54,10 @@ public class SoundController extends BaseController {
         if(!WebSocketHandler.WS_CLIENTS.containsKey(phone)){
             return failed("未上线");
         }
-        if(!WebSocketHandler.WS_CLIENTS.get(phone).isOpen()){
+        if(!WebSocketHandler.WS_CLIENTS.get(phone).getSession().isOpen()){
             return failed("已离线");
         }
-        WebSocketHandler.WS_CLIENTS.get(phone).sendMessage(new TextMessage(message));
+        WebSocketHandler.WS_CLIENTS.get(phone).getSession().sendMessage(new TextMessage(message));
         return succeed();
     }
 
@@ -66,10 +66,10 @@ public class SoundController extends BaseController {
         if(!WebSocketHandler.WS_CLIENTS.containsKey(phone)){
             return failed("未上线");
         }
-        if(!WebSocketHandler.WS_CLIENTS.get(phone).isOpen()){
+        if(!WebSocketHandler.WS_CLIENTS.get(phone).getSession().isOpen()){
             return failed("已离线");
         }
-        WebSocketHandler.WS_CLIENTS.get(phone).close();
+        WebSocketHandler.WS_CLIENTS.get(phone).getSession().close();
         return succeed();
     }
 

+ 41 - 0
mec-web/src/main/java/com/ym/mec/web/config/WebSocketConfig.java

@@ -0,0 +1,41 @@
+package com.ym.mec.web.config;
+
+import com.ym.mec.biz.handler.WebSocketHandler;
+import com.ym.mec.web.interceptor.WebSocketHandshakeInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/6/8 0008
+ */
+@Configuration
+@EnableWebSocket
+public class WebSocketConfig implements WebSocketConfigurer {
+
+    @Autowired
+    private WebSocketHandler webSocketHandler;
+    @Autowired
+    private WebSocketHandshakeInterceptor webSocketHandshakeInterceptor;
+
+    @Override
+    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
+        webSocketHandlerRegistry.addHandler(webSocketHandler, "/audioEvaluate")
+                .addInterceptors(webSocketHandshakeInterceptor)
+                .setAllowedOrigins("*");
+    }
+
+    @Bean
+    public ServletServerContainerFactoryBean createWebSocketContainer() {
+        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
+        container.setMaxTextMessageBufferSize(8192*4);
+        container.setMaxBinaryMessageBufferSize(8192*4);
+        return container;
+    }
+
+}

+ 28 - 0
mec-web/src/main/java/com/ym/mec/web/interceptor/WebSocketHandshakeInterceptor.java

@@ -0,0 +1,28 @@
+package com.ym.mec.web.interceptor;
+
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.server.HandshakeInterceptor;
+
+import java.util.Map;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/6/9 0009
+ */
+@Component
+public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
+
+    @Override
+    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
+        return true;
+    }
+
+    @Override
+    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
+
+    }
+
+}