Joburgess před 4 roky
rodič
revize
70082ebb34

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

@@ -1,8 +1,10 @@
 package com.ym.mec.biz.handler;
 
 import be.tarsos.dsp.AudioDispatcher;
+import be.tarsos.dsp.SilenceDetector;
 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;
@@ -46,12 +48,13 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
     public static final Map<String, WebSocketSession> WS_CLIENTS = new ConcurrentHashMap<>();
 
     private final BigDecimal oneHundred = new BigDecimal(100);
-    private final float simpleRate = 44200;
-    private final int simpleSize = 512;
+    private final float simpleRate = 44100;
+    private final int simpleSize = 1024;
     private final int overlap = 256;
 
     private final AudioFormat audioFormat = new AudioFormat(simpleRate, 16, 1, true, false);
     private static final PitchProcessor.PitchEstimationAlgorithm algo = PitchProcessor.PitchEstimationAlgorithm.FFT_YIN;
+    private final SilenceDetector silenceDetecor = new SilenceDetector();
 
     private final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/";
 
@@ -158,10 +161,18 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 
         List<MusicPitchDetailDto> recordInfo = new ArrayList<>();
         AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), audioFormat, simpleSize, overlap);
+        dispatcher.addAudioProcessor(silenceDetecor);
         dispatcher.addAudioProcessor(new PitchProcessor(algo, simpleRate, simpleSize, (pitchDetectionResult, audioEvent) -> {
             int timeStamp = (int) (userSoundInfoMap.get(phone).getMeasureStartTime() + audioEvent.getTimeStamp()*1000);
             float pitch = pitchDetectionResult.getPitch();
-//            LOGGER.info("频率:{}, {}", timeStamp, pitch);
+            double cents = 0;
+            if (pitch > 0) {
+                cents = PitchConverter.hertzToRelativeCent(pitch);
+            }
+            LOGGER.info("时间:{}, 频率:{}, 分贝:{}, 音分:{}", timeStamp, pitch, silenceDetecor.currentSPL(), cents);
+            if (silenceDetecor.currentSPL() <= -50){
+                pitch = -1;
+            }
             recordInfo.add(new MusicPitchDetailDto(timeStamp, pitch));
         }));
         dispatcher.run();
@@ -318,7 +329,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
                 //时间范围内匹配次数
                 float compareNum = 0;
 
-                boolean newMeasure = true;
+                boolean newMeasure = false;
                 float preMusicalNotesPitch = 0;
                 if(userSoundInfoMap.get(phone).getMusicalNotePitchMap().containsKey(musicXmlInfo.getMusicalNotesIndex()-1)){
                     preMusicalNotesPitch = userSoundInfoMap.get(phone).getMusicalNotePitchMap().get(musicXmlInfo.getMusicalNotesIndex()-1);
@@ -357,11 +368,11 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
                         continue;
                     }
                     musicalNotesPitchs.add((int) recordInfo.getFrequency());
+                    compareNum++;
                     if(!newMeasure){
                         continue;
                     }
 //                    LOGGER.info("{}频率({}-{}):{}, {}", recordInfo.getTimeStamp(), startTimeStamp, endTimeStamp, musicXmlInfo.getFrequency(), recordInfo.getFrequency());
-                    compareNum++;
                     //如果在最低有效频率以下则跳过
                     if(recordInfo.getFrequency()<minValidFrequency&&musicXmlInfo.getFrequency()!=-1){
                         continue;
@@ -386,7 +397,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
                 if(CollectionUtils.isEmpty(musicalNotesPitchs)){
                     userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(musicXmlInfo.getMusicalNotesIndex(), (float) 0);
                 }else{
-                    Map<Integer, Long> collect = musicalNotesPitchs.stream().filter(pitch->pitch>0).collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()));
+                    Map<Integer, Long> collect = musicalNotesPitchs.stream().collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()));
                     //出现次数最多的频率
                     Integer pitch = collect.entrySet().stream().max(Comparator.comparing(e -> e.getValue())).get().getKey();
                     boolean ing = false;
@@ -410,7 +421,9 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
                 }
 
                 //有效音频占比
-                integrityValidNum = integrityValidNum + (float) (compareNum * 0.05);
+                if(integrityValidNum>0){
+                    integrityValidNum = integrityValidNum + (float) (compareNum * 0.05);
+                }
                 if(integrityValidNum > compareNum){
                     integrityValidNum = compareNum;
                 }
@@ -421,9 +434,9 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
                 //有效节奏占比
                 float cadenceDuty = cadenceValidNum/compareNum;
                 //如果错误频率达到一定数值,则当前小节无效
-//                if(errPitchNum>=3){
-//                    cadenceDuty = 0;
-//                }
+                if(errPitchNum>=2){
+                    cadenceDuty = 0;
+                }
                 //节奏
                 if(cadenceDuty>=cadenceValidDuty){
                     cadenceNum++;
@@ -682,8 +695,8 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         webSocketInfo.setHeader(header);
         Map<String, Object> result = new HashMap<>();
 //        BigDecimal score = intonation.multiply(new BigDecimal(0.5)).add(cadence.multiply(new BigDecimal(0.5))).setScale(0, BigDecimal.ROUND_HALF_UP);
-//        BigDecimal score = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_HALF_UP);
-        BigDecimal score = integrity.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_HALF_UP);
+//        BigDecimal score = integrity.setScale(0, BigDecimal.ROUND_HALF_UP);
         result.put("score", score);
         result.put("intonation", intonation);
         result.put("cadence", cadence);