Browse Source

Merge branch 'music_score'

# Conflicts:
#	mec-biz/src/main/java/com/ym/mec/biz/service/impl/SoundCompareHandler.java
Joburgess 4 years ago
parent
commit
140d9bfd02

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

@@ -35,7 +35,7 @@ public class SoundCompareConfig {
     /**
      * @describe 有效分贝大小
      */
-    public int validDb = -70;
+    public int validDb = 20;
     /**
      * @describe 有效频率
      */

+ 53 - 55
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/SoundCompareHelper.java

@@ -9,6 +9,7 @@ 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;
 
 import java.io.File;
 import java.io.RandomAccessFile;
@@ -82,6 +83,10 @@ public class SoundCompareHelper implements PitchDetectionHandler {
 
     private List<MusicPitchDetailDto> musicXmlInfos;
 
+    private long firstMeasureStartBytes = 0;
+
+    private long recordBytes = 0;
+
     private String clientId;
 
     private Integer detailId;
@@ -280,6 +285,22 @@ public class SoundCompareHelper implements PitchDetectionHandler {
         this.userScoreMap = userScoreMap;
     }
 
+    public long getFirstMeasureStartBytes() {
+        return firstMeasureStartBytes;
+    }
+
+    public void setFirstMeasureStartBytes(long firstMeasureStartBytes) {
+        this.firstMeasureStartBytes = firstMeasureStartBytes;
+    }
+
+    public long getRecordBytes() {
+        return recordBytes;
+    }
+
+    public void setRecordBytes(long recordBytes) {
+        this.recordBytes = recordBytes;
+    }
+
     public Map<Integer, Map<String, Object>> getUserMeasureScoreMap() {
         return userMeasureScoreMap;
     }
@@ -300,70 +321,47 @@ public class SoundCompareHelper implements PitchDetectionHandler {
     public void handlePitch(PitchDetectionResult pitchDetectionResult, AudioEvent audioEvent) {
         int timeStamp = (int) (measureStartTime + audioEvent.getTimeStamp()*1000);
         float pitch = pitchDetectionResult.getPitch();
-        double decibel = silenceDetector.currentSPL();
-        //初始化偏移时间
-        if(offsetTime == -1 && !DeviceTypeEnum.IOS.equals(deviceType) && pitch>0){
-            offsetTime = timeStamp;
-            for (MusicPitchDetailDto musicXmlInfo : musicXmlInfos) {
-                if(!musicXmlInfo.getDontEvaluating()){
-                    if(offsetTime > musicXmlInfo.getTimeStamp()) {
-                        offsetTime = offsetTime - musicXmlInfo.getTimeStamp();
-                    }
-                    break;
-                }
-            }
-            musicXmlInfos.forEach(e->e.setTimeStamp(e.getTimeStamp()+offsetTime));
-            for (Map.Entry<Integer, MusicPitchDetailDto> musicPitchDetailDtoEntry : measureEndTime.entrySet()) {
-                musicPitchDetailDtoEntry.getValue().setTimeStamp(musicPitchDetailDtoEntry.getValue().getTimeStamp() + offsetTime);
-                musicPitchDetailDtoEntry.getValue().setEndTimeStamp(musicPitchDetailDtoEntry.getValue().getEndTimeStamp() + offsetTime);
-            }
-        }
+        int decibel = (int) (100 - Math.abs(silenceDetector.currentSPL()));
 
-        if(decibel < SoundCompareHandler.soundCompareConfig.validDb){
-            decibel = SoundCompareHandler.soundCompareConfig.validDb;
+        if(decibel <= SoundCompareHandler.soundCompareConfig.validDb){
             pitch = -1;
-        }
-        if(pitch==-1){
-            decibel = SoundCompareHandler.soundCompareConfig.validDb;
-        }
-//        SoundCompareHandler.LOGGER.info("时间:{}, 频率:{}, 分贝:{}", timeStamp, pitch, decibel);
-//        recordMeasurePithInfo.add(new MusicPitchDetailDto(timeStamp, pitch, silenceDetector.currentSPL()));
-
-        Double avgPitch = currPitchInfos.stream().skip(1).collect(Collectors.averagingDouble(MusicPitchDetailDto::getFrequency));
-        Double avgDb = currPitchInfos.stream().skip(1).collect(Collectors.averagingDouble(MusicPitchDetailDto::getDecibel));
-        long count = currPitchInfos.stream().filter(p -> p.getFrequency() < 0).count();
-        if(currPitchInfos.size()>0&&count/currPitchInfos.size()<0.5){
-            avgPitch = currPitchInfos.stream().skip(1).filter(p->p.getFrequency()>0).collect(Collectors.averagingDouble(MusicPitchDetailDto::getFrequency));
-        }
-        if(Math.abs(avgPitch-pitch)>10||Math.abs(decibel-avgDb)>5){
-            obviousChangeNum++;
-        }else{
-            currTmpPitchInfos.clear();
-            obviousChangeNum=0;
+            decibel = 0;
         }
 
-        if(obviousChangeNum>1){
-//            SoundCompareHandler.LOGGER.info("----------------------------{}----{}", avgPitch, recordMeasurePitchInfos.size());
-//            SoundCompareHandler.LOGGER.info("----------------------------{}", JSON.toJSONString(currPitchInfos.stream().map(MusicPitchDetailDto::getFrequency).collect(Collectors.toList())));
-//            SoundCompareHandler.LOGGER.info("----------------------------{}", JSON.toJSONString(currTmpPitchInfos.stream().map(MusicPitchDetailDto::getFrequency).collect(Collectors.toList())));
+        SoundCompareHandler.LOGGER.info("时间:{}, 频率:{}, 分贝:{}", timeStamp, pitch, decibel);
 
-            if(avgPitch>0&&currPitchInfos.size()>2){
-                MusicPitchDetailDto measureDetail = new MusicPitchDetailDto(currPitchInfos.get(0).getTimeStamp(), avgPitch.floatValue(), avgDb);
-                measureDetail.setEndTimeStamp(currTmpPitchInfos.get(0).getTimeStamp());
-                measureDetail.setDuration(measureDetail.getEndTimeStamp()-measureDetail.getTimeStamp());
+        if(currPitchInfos.size()>0&&(Math.abs(currPitchInfos.get(currPitchInfos.size()-1).getFrequency()-pitch)>10||Math.abs(currPitchInfos.get(currPitchInfos.size()-1).getDecibel()-decibel)>10)){
+            Double avgPitch = currPitchInfos.stream().skip(1).collect(Collectors.averagingDouble(MusicPitchDetailDto::getFrequency));
+            Double avgDb = currPitchInfos.stream().skip(1).collect(Collectors.averagingDouble(MusicPitchDetailDto::getDecibel));
+
+            MusicPitchDetailDto measureDetail = new MusicPitchDetailDto(currPitchInfos.get(0).getTimeStamp(), avgPitch.floatValue(), avgDb);
+            measureDetail.setEndTimeStamp(timeStamp);
+            measureDetail.setDuration(measureDetail.getEndTimeStamp()-measureDetail.getTimeStamp());
+
+            if(measureDetail.getDuration()>25&&(avgPitch>0||avgDb>SoundCompareHandler.soundCompareConfig.validDb)){
                 recordMeasurePitchInfos.add(measureDetail);
             }
 
             currPitchInfos.clear();
-            currPitchInfos.addAll(currTmpPitchInfos);
-            currTmpPitchInfos.clear();
-            obviousChangeNum = 0;
-        }
-        if(obviousChangeNum>0){
-            currTmpPitchInfos.add(new MusicPitchDetailDto(timeStamp, pitch, decibel));
-        }else{
-            currPitchInfos.add(new MusicPitchDetailDto(timeStamp, pitch, decibel));
-        }
 
+            //初始化偏移时间
+            if(offsetTime == -1 && recordMeasurePitchInfos.size() == 1){
+                offsetTime = recordMeasurePitchInfos.get(0).getTimeStamp();
+                for (MusicPitchDetailDto musicXmlInfo : musicXmlInfos) {
+                    if(!musicXmlInfo.getDontEvaluating()){
+                        if(offsetTime > musicXmlInfo.getTimeStamp()) {
+                            offsetTime = offsetTime - musicXmlInfo.getTimeStamp();
+                        }
+                        break;
+                    }
+                }
+                musicXmlInfos.forEach(e->e.setTimeStamp(e.getTimeStamp()+offsetTime));
+                for (Map.Entry<Integer, MusicPitchDetailDto> musicPitchDetailDtoEntry : measureEndTime.entrySet()) {
+                    musicPitchDetailDtoEntry.getValue().setTimeStamp(musicPitchDetailDtoEntry.getValue().getTimeStamp() + offsetTime);
+                    musicPitchDetailDtoEntry.getValue().setEndTimeStamp(musicPitchDetailDtoEntry.getValue().getEndTimeStamp() + offsetTime);
+                }
+            }
+        }
+        currPitchInfos.add(new MusicPitchDetailDto(timeStamp, pitch, decibel));
     }
 }

+ 38 - 22
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SoundCompareHandler.java

@@ -32,7 +32,6 @@ import org.springframework.web.socket.WebSocketSession;
 
 import javax.sound.sampled.UnsupportedAudioFileException;
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.math.BigDecimal;
@@ -97,6 +96,7 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                 userSoundInfoMap.put(phone, new SoundCompareHelper());
                 userSoundInfoMap.get(phone).setClientId(((OAuth2Authentication)session.getPrincipal()).getOAuth2Request().getClientId());
                 List<MusicPitchDetailDto> musicXmlInfos = JSON.parseArray(bodyObject.getString("musicXmlInfos"), MusicPitchDetailDto.class);
+                userSoundInfoMap.get(phone).setFirstMeasureStartBytes((long) (0*(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())));
                 userSoundInfoMap.get(phone).setMusicXmlInfos(musicXmlInfos);
                 musicXmlInfos = musicXmlInfos.stream().filter(m->!m.getDontEvaluating()).collect(Collectors.toList());
                 userSoundInfoMap.get(phone).setMusicScoreId(bodyObject.getInteger("id"));
@@ -180,10 +180,10 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                 createHeader(phone, false);
                 break;
             case SoundSocketService.PROXY_MESSAGE:
-                if(DeviceTypeEnum.IOS.equals(userSoundInfoMap.get(phone).getDeviceType())&&bodyObject.containsKey(SoundSocketService.OFFSET_TIME)){
-                    int offsetTime = bodyObject.getIntValue(SoundSocketService.OFFSET_TIME);
-                    calOffsetTime(phone, offsetTime);
-                }
+//                if(DeviceTypeEnum.IOS.equals(userSoundInfoMap.get(phone).getDeviceType())&&bodyObject.containsKey(SoundSocketService.OFFSET_TIME)){
+//                    int offsetTime = bodyObject.getIntValue(SoundSocketService.OFFSET_TIME);
+//                    calOffsetTime(phone, offsetTime);
+//                }
                 break;
             case VIDEO_UPDATE:
                 SysMusicCompareRecord update = null;
@@ -209,22 +209,25 @@ public class SoundCompareHandler implements WebSocketEventHandler {
         if(!userSoundInfoMap.containsKey(phone)){
             return;
         }
+        userSoundInfoMap.get(phone).setRecordBytes(userSoundInfoMap.get(phone).getRecordBytes()+message.getPayloadLength());
+        if(userSoundInfoMap.get(phone).getRecordBytes()<userSoundInfoMap.get(phone).getFirstMeasureStartBytes()){
+            return;
+        }
         try {
             if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
                 userSoundInfoMap.get(phone).getAccessFile().write(message.getPayload().array());
+            }else{
+                return;
             }
 
             AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), soundCompareConfig.audioFormat, soundCompareConfig.simpleSize, soundCompareConfig.overlap);
-
             dispatcher.addAudioProcessor(userSoundInfoMap.get(phone).silenceDetector);
             dispatcher.addAudioProcessor(new PitchProcessor(soundCompareConfig.algo, soundCompareConfig.simpleRate, soundCompareConfig.simpleSize, userSoundInfoMap.get(phone)));
             dispatcher.run();
-            if(Objects.isNull(userSoundInfoMap.get(phone).getAccessFile())){
-                return;
-            }
 
             double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
             userSoundInfoMap.get(phone).setMeasureStartTime(recordTime);
+
             for (Map.Entry<Integer, MusicPitchDetailDto> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
                 if(recordTime>(userMeasureEndTimeMapEntry.getValue().getEndTimeStamp()+100)){
                     if(userMeasureEndTimeMapEntry.getValue().getDontEvaluating()){
@@ -353,9 +356,10 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                 int startTimeStamp = musicXmlInfo.getTimeStamp();
                 int endTimeStamp = musicXmlInfo.getTimeStamp() + musicXmlInfo.getDuration();
 
-                int ot5 = (int) (musicXmlInfo.getDuration()*0.1);
+                int ot5 = (int) (musicXmlInfo.getDuration()*0.22<70?70:musicXmlInfo.getDuration()*0.22);
+                int rightTimeRange = ot5>200?200:ot5;
 
-                List<MusicPitchDetailDto> recordPitchs = userSoundInfoMap.get(phone).getRecordMeasurePitchInfos().stream().filter(m -> Math.abs(startTimeStamp-m.getTimeStamp())<ot5 || (m.getTimeStamp() >= startTimeStamp && m.getTimeStamp() <= endTimeStamp)).collect(Collectors.toList());
+                List<MusicPitchDetailDto> recordPitchs = userSoundInfoMap.get(phone).getRecordMeasurePitchInfos().stream().filter(m -> m.getTimeStamp()>=startTimeStamp-rightTimeRange && m.getTimeStamp() < endTimeStamp-rightTimeRange).collect(Collectors.toList());
 
                 boolean cadenceRight = false;
                 boolean intonationRight = false;
@@ -367,7 +371,7 @@ public class SoundCompareHandler implements WebSocketEventHandler {
                 }
                 integrityDuty = scoreMapping(integrityDuty, userSoundInfoMap.get(phone).getHeardLevel().getIntegrityRange(), 1);
                 //节奏
-                if(recordPitchs.size()==1||integrityDuty>userSoundInfoMap.get(phone).getHeardLevel().getCadenceRange()){
+                if(recordPitchs.size()==1){
                     cadenceNum++;
                     cadenceRight = true;
                 }
@@ -393,16 +397,32 @@ public class SoundCompareHandler implements WebSocketEventHandler {
 
                     score = Math.pow(score/100f, userSoundInfoMap.get(phone).getHeardLevel().getIntonationCentsRange())*100;
 
+                    if(Objects.nonNull(userSoundInfoMap.get(phone).getSubjectId())&&userSoundInfoMap.get(phone).getSubjectId()==23){
+                        score = 100;
+                        integrityDuty = 1;
+                    }
+
                     intonationScore += score;
                     musicXmlInfo.setAvgFrequency(avgPitch);
                     intonationRight = score>70;
-                }
-                //完成度
-                if(cadenceRight){
+
                     integrityScore += integrityDuty;
                     integrityRight = integrityDuty>0.7;
                 }
 
+                //如果当前音符不需要演奏
+                if (musicXmlInfo.getFrequency()<0&&recordPitchs.size()<=0){
+                    cadenceNum++;
+                    cadenceRight = true;
+
+                    intonationScore += 100;
+                    musicXmlInfo.setAvgFrequency(-1);
+                    intonationRight = true;
+
+                    integrityScore += 1;
+                    integrityRight = true;
+                }
+
                 if(!cadenceRight){
                     userSoundInfoMap.get(phone).getMusicalNotesPlayStats().add(new MusicalNotesPlayStatDto(musicXmlInfo.getMusicalNotesIndex(), MusicalErrorTypeEnum.CADENCE_WRONG));
                 }else if(!intonationRight){
@@ -493,12 +513,8 @@ public class SoundCompareHandler implements WebSocketEventHandler {
         WebSocketInfo webSocketInfo = new WebSocketInfo();
         webSocketInfo.setHeader(new WebSocketInfo.Head(command));
         Map<String, Object> result = new HashMap<>(5);
-        //打击乐只看节奏分
-        BigDecimal score = cadence;
-        //非打击乐总分为平均分
-        if(Objects.isNull(userSoundInfoMap.get(phone).getSubjectId())||userSoundInfoMap.get(phone).getSubjectId()!=23){
-            score = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP);
-        }
+        BigDecimal score  = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP);
+
         result.put("score", score);
         result.put("intonation", intonation);
         result.put("cadence", cadence);
@@ -509,7 +525,7 @@ public class SoundCompareHandler implements WebSocketEventHandler {
 
         userSoundInfoMap.get(phone).getUserMeasureScoreMap().put(measureIndex, result);
 
-        LOGGER.info("小节评分:{}", JSON.toJSONString(webSocketInfo));
+        LOGGER.info("{}小节评分:{}", phone, JSON.toJSONString(webSocketInfo));
 
         //推送结果
         WebSocketHandler.sendTextMessage(phone, webSocketInfo);

+ 2 - 2
mec-websocket/src/main/java/com/ym/mec/web/config/WebSocketConfig.java

@@ -33,8 +33,8 @@ public class WebSocketConfig implements WebSocketConfigurer {
     @Bean
     public ServletServerContainerFactoryBean createWebSocketContainer() {
         ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
-        container.setMaxTextMessageBufferSize(8192*4);
-        container.setMaxBinaryMessageBufferSize(8192*4);
+        container.setMaxTextMessageBufferSize(8192*9);
+        container.setMaxBinaryMessageBufferSize(8192*9);
         return container;
     }