|
@@ -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);
|