Browse Source

feat:智能陪练一期

Joburgess 3 years ago
parent
commit
864562e65e

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/SoundCompareHelper.java

@@ -5,6 +5,7 @@ import be.tarsos.dsp.SilenceDetector;
 import be.tarsos.dsp.pitch.PitchDetectionHandler;
 import be.tarsos.dsp.pitch.PitchDetectionResult;
 import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
+import com.ym.mec.biz.dal.enums.HeardLevelEnum;
 import com.ym.mec.biz.service.impl.SoundCompareHandler;
 import io.swagger.annotations.ApiModelProperty;
 import org.springframework.util.CollectionUtils;
@@ -35,6 +36,9 @@ public class SoundCompareHelper implements PitchDetectionHandler {
     @ApiModelProperty(value = "声部编号")
     private Integer subjectId;
 
+    @ApiModelProperty(value = "评测等级")
+    private HeardLevelEnum heardLevel = HeardLevelEnum.BEGINNER;
+
     @ApiModelProperty(value = "小节开始时间")
     private double measureStartTime = 0;
 
@@ -116,6 +120,14 @@ public class SoundCompareHelper implements PitchDetectionHandler {
         this.subjectId = subjectId;
     }
 
+    public HeardLevelEnum getHeardLevel() {
+        return heardLevel;
+    }
+
+    public void setHeardLevel(HeardLevelEnum heardLevel) {
+        this.heardLevel = heardLevel;
+    }
+
     public DeviceTypeEnum getDeviceType() {
         return deviceType;
     }

+ 8 - 4
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/WebSocketInfo.java

@@ -14,14 +14,14 @@ public class WebSocketInfo<T> {
     private T body;
 
     public static class Head{
-        private HttpStatus status = HttpStatus.OK;
+        private int status = HttpStatus.OK.value();
         private String commond = "";
         private WebsocketTypeEnum type;
 
         public Head() {
         }
 
-        public Head(HttpStatus status) {
+        public Head(int status) {
             this.status = status;
         }
 
@@ -34,11 +34,11 @@ public class WebSocketInfo<T> {
             this.type = type;
         }
 
-        public HttpStatus getStatus() {
+        public int getStatus() {
             return status;
         }
 
-        public void setStatus(HttpStatus status) {
+        public void setStatus(int status) {
             this.status = status;
         }
 
@@ -70,6 +70,10 @@ public class WebSocketInfo<T> {
         return new WebSocketInfo(new Head());
     }
 
+    public static WebSocketInfo success(String commond){
+        return new WebSocketInfo(new Head(commond));
+    }
+
 
     public Head getHeader() {
         return header;

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicCompareRecord.java

@@ -2,6 +2,7 @@ package com.ym.mec.biz.dal.entity;
 
 import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
 import com.ym.mec.biz.dal.enums.FeatureType;
+import com.ym.mec.biz.dal.enums.HeardLevelEnum;
 import com.ym.mec.util.date.DateUtil;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
@@ -26,6 +27,8 @@ public class SysMusicCompareRecord {
 	/** 教程编号 */
 	private Integer sysMusicScoreId;
 
+	private HeardLevelEnum heardLevel;
+
 	private String sysMusicScoreName;
 	
 	/** 评分数据 */
@@ -92,6 +95,14 @@ public class SysMusicCompareRecord {
 		this.clientId = clientId;
 	}
 
+	public HeardLevelEnum getHeardLevel() {
+		return heardLevel;
+	}
+
+	public void setHeardLevel(HeardLevelEnum heardLevel) {
+		this.heardLevel = heardLevel;
+	}
+
 	public void setSysMusicScoreId(Integer sysMusicScoreId){
 		this.sysMusicScoreId = sysMusicScoreId;
 	}

+ 71 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/HeardLevelEnum.java

@@ -0,0 +1,71 @@
+package com.ym.mec.biz.dal.enums;
+
+import com.ym.mec.common.enums.BaseEnum;
+
+public enum HeardLevelEnum implements BaseEnum<String, HeardLevelEnum> {
+    BEGINNER("BEGINNER","初学者", 9, 0.05f, 0),
+    ADVANCED("ADVANCED","进阶者", 3, 0.09f, 0),
+    PERFORMER("PERFORMER","小演奏家", 1, 0.3f, 0);
+
+    private String code;
+
+    private String msg;
+
+    /** 音准音分偏差数 */
+    private float intonationCentsRange;
+
+    /** 节奏评分截取时间占比 */
+    private float cadenceRange;
+
+    /** 完整性 */
+    private float integrityRange;
+
+    HeardLevelEnum(String code, String msg, float intonationCentsRange, float cadenceRange, float integrityRange) {
+        this.code = code;
+        this.msg = msg;
+        this.intonationCentsRange = intonationCentsRange;
+        this.cadenceRange = cadenceRange;
+        this.integrityRange = integrityRange;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    @Override
+    public String getCode() {
+        return this.code;
+    }
+
+    public float getIntonationCentsRange() {
+        return intonationCentsRange;
+    }
+
+    public void setIntonationCentsRange(float intonationCentsRange) {
+        this.intonationCentsRange = intonationCentsRange;
+    }
+
+    public float getCadenceRange() {
+        return cadenceRange;
+    }
+
+    public void setCadenceRange(float cadenceRange) {
+        this.cadenceRange = cadenceRange;
+    }
+
+    public float getIntegrityRange() {
+        return integrityRange;
+    }
+
+    public void setIntegrityRange(float integrityRange) {
+        this.integrityRange = integrityRange;
+    }
+}

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

@@ -109,7 +109,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
     public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
         super.afterConnectionClosed(session, status);
         String phone = session.getPrincipal().getName().split(":")[1];
-        LOGGER.info("{}离线", phone);
+        LOGGER.info("{}离线: {}s", phone, (System.currentTimeMillis() - WS_CLIENTS.get(phone).getLoginTime().getTime())*1000);
         appMap.values().forEach(e->e.afterConnectionClosed(session, phone));
         WS_CLIENTS.remove(phone);
     }

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

@@ -9,6 +9,7 @@ public interface SoundSocketService {
     String TAG = "TAG";
     String COMMOND = "commond";
     String MUSIC_XML = "musicXml";
+    String CHECK_END = "checkEnd";
     String RECORD_START = "recordStart";
     String RECORD_END = "recordEnd";
     String RECORD_CANCEL = "recordCancel";

+ 18 - 3
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SoundCheckHandler.java

@@ -6,6 +6,7 @@ import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
 import be.tarsos.dsp.pitch.PitchDetectionHandler;
 import be.tarsos.dsp.pitch.PitchDetectionResult;
 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;
@@ -51,7 +52,14 @@ public class SoundCheckHandler implements WebSocketEventHandler {
 
     @Override
     public void receiveTextMessage(WebSocketSession session, String phone, WebSocketInfo message) {
-        userSoundCheckInfo.put(phone, 0);
+        switch (message.getHeader().getCommond()) {
+            case SoundSocketService.CHECK_END:
+                userSoundCheckInfo.remove(phone);
+                break;
+            default:
+                userSoundCheckInfo.put(phone, 0);
+                break;
+        }
     }
 
     @Override
@@ -62,13 +70,20 @@ public class SoundCheckHandler implements WebSocketEventHandler {
         try {
             AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), SoundCompareHandler.soundCompareConfig.audioFormat, SoundCompareHandler.soundCompareConfig.simpleSize, SoundCompareHandler.soundCompareConfig.overlap);
             dispatcher.addAudioProcessor(new PitchProcessor(SoundCompareHandler.soundCompareConfig.algo, SoundCompareHandler.soundCompareConfig.simpleRate, SoundCompareHandler.soundCompareConfig.simpleSize, (pitchDetectionResult, audioEvent) -> {
-
+                if(pitchDetectionResult.getPitch()<=0){
+                    return;
+                }
+                double normalCents = PitchConverter.hertzToAbsoluteCent(COMPARE_FREQUENCY);
+                double recordCents = PitchConverter.hertzToAbsoluteCent(pitchDetectionResult.getPitch());
+                if(Math.abs(normalCents - recordCents)<3){
+                    WebSocketHandler.sendTextMessage(phone, WebSocketInfo.success("checkDone"));
+                    userSoundCheckInfo.remove(phone);
+                }
             }));
             dispatcher.run();
         } catch (UnsupportedAudioFileException e) {
             throw new BizException("{}校音异常:{}", phone, e);
         }
-        WebSocketHandler.sendTextMessage(phone, WebSocketInfo.success());
     }
 
     @Override

+ 13 - 5
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SoundCompareHandler.java

@@ -10,6 +10,7 @@ import com.ym.mec.biz.dal.config.SoundCompareConfig;
 import com.ym.mec.biz.dal.dao.SysMusicScoreAccompanimentDao;
 import com.ym.mec.biz.dal.dto.*;
 import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
+import com.ym.mec.biz.dal.enums.HeardLevelEnum;
 import com.ym.mec.biz.dal.enums.MusicalErrorTypeEnum;
 import com.ym.mec.biz.dal.enums.WebsocketTypeEnum;
 import com.ym.mec.biz.handler.WebSocketHandler;
@@ -110,6 +111,9 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                 if(bodyObject.containsKey("xmlUrl")){
                     userSoundInfoMap.get(phone).setXmlUrl(bodyObject.getString("xmlUrl"));
                 }
+                if(bodyObject.containsKey("heardLevel")){
+                    userSoundInfoMap.get(phone).setHeardLevel(HeardLevelEnum.valueOf(bodyObject.getString("heardLevel")));
+                }
                 List<Integer> subjectIds = sysMusicScoreAccompanimentDao.findSubjectByMusicScoreId(userSoundInfoMap.get(phone).getMusicScoreId(), null);
                 if(!CollectionUtils.isEmpty(subjectIds)){
                     userSoundInfoMap.get(phone).setSubjectId(subjectIds.get(0));
@@ -154,9 +158,10 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                             userSoundInfoMap.get(phone).getMeasureEndTime().remove(lastMeasureIndex);
                         }
                     }
+                } catch (IOException | NullPointerException e) {
+                    LOGGER.error("评分错误:", e);
+                } finally {
                     calTotalScore(phone);
-                } catch (IOException e) {
-                    throw new BizException("评分错误:", e);
                 }
                 createHeader(phone);
                 break;
@@ -407,12 +412,13 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                     cadenceDuty = 0;
                 }
                 //节奏
-                if(cadenceDuty>=soundCompareConfig.cadenceValidDuty){
+                if(cadenceDuty>=userSoundInfoMap.get(phone).getHeardLevel().getCadenceRange()){
                     cadenceNum++;
                     cadenceRight = true;
                 }
-                //音准
+                //音准、完成度
                 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;
@@ -423,7 +429,7 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                     if(musicXmlInfo.getFrequency()>0){
                         cents =  PitchConverter.hertzToAbsoluteCent(musicXmlInfo.getFrequency());
                     }
-                    double score = 100 - Math.round(Math.abs(cents - recordCents)) + soundCompareConfig.intonationCentsRange;
+                    double score = 100 - Math.round(Math.abs(cents - recordCents)) + userSoundInfoMap.get(phone).getHeardLevel().getIntonationCentsRange();
                     if (score < 0){
                         score = 0;
                     }else if(score > 100){
@@ -432,6 +438,8 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                     intonationScore += score;
                     musicXmlInfo.setAvgFrequency(avgPitch.floatValue());
                     intonationRight = score>70;
+
+                    integrityValidNum = measureSoundPitchInfos.stream().filter(pitch -> Math.abs((pitch.getFrequency()-musicXmlInfo.getFrequency()))<5).count();
                 }
                 //完成度
                 if(integrityValidNum > compareNum){

+ 1 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java

@@ -60,6 +60,7 @@ public class SysMusicCompareRecordServiceImpl extends BaseServiceImpl<Long, SysM
 		SysMusicCompareRecord sysMusicCompareRecord = new SysMusicCompareRecord();
 		sysMusicCompareRecord.setUserId(user.getId());
 		sysMusicCompareRecord.setSysMusicScoreId(soundCompareInfo.getMusicScoreId());
+		sysMusicCompareRecord.setHeardLevel(soundCompareInfo.getHeardLevel());
 		sysMusicCompareRecord.setBehaviorId(soundCompareInfo.getBehaviorId());
 		Map<String, Object> scoreData = new HashMap<>();
 		scoreData.put("userMeasureScore", soundCompareInfo.getUserMeasureScoreMap());

+ 5 - 3
mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml

@@ -10,6 +10,7 @@
 		<result column="id_" property="id" />
 		<result column="user_id_" property="userId" />
 		<result column="sys_music_score_id_" property="sysMusicScoreId" />
+		<result column="heard_level_" property="heardLevel" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler" />
 		<result column="sys_music_score_name_" property="sysMusicScoreName" />
 		<result column="behavior_id_" property="behaviorId"/>
 		<result column="score_data_" property="scoreData" />
@@ -43,10 +44,11 @@
 		SELECT SEQ_WSDEFINITION_ID.nextval AS ID FROM DUAL 
 		</selectKey>
 		-->
-		INSERT INTO sys_music_compare_record (id_,user_id_,sys_music_score_id_,behavior_id_,score_data_,score_,intonation_,cadence_,integrity_,
+		INSERT INTO sys_music_compare_record (id_,user_id_,sys_music_score_id_,heard_level_,behavior_id_,score_data_,score_,intonation_,cadence_,integrity_,
 		                                      record_file_path_,device_type_,client_id_,play_time_,monday_,
 											feature_,create_time_)
-		VALUES(#{id},#{userId},#{sysMusicScoreId},#{behaviorId},#{scoreData},#{score},#{intonation},#{cadence},#{integrity},
+		VALUES(#{id},#{userId},#{sysMusicScoreId},#{heardLevel,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{behaviorId},#{scoreData},
+		       #{score},#{intonation},#{cadence},#{integrity},
 		       #{recordFilePath},#{deviceType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{clientId},#{playTime},#{monday},
 		       #{feature,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}, NOW())
 	</insert>
@@ -166,7 +168,7 @@
 	<select id="getUserTrainChartData" resultType="com.ym.mec.biz.dal.dto.StudentTrainChartDto">
 		SELECT
 			DATE_FORMAT(smcr.create_time_, '%Y-%m-%d') trainDate,
-			COUNT(smcr.id_) trainNum,
+			COUNT(DISTINCT smcr.behavior_id_) trainNum,
 			SUM(smcr.play_time_) trainTime
 		FROM sys_music_compare_record smcr
 		WHERE smcr.user_id_=#{userId}