|
@@ -0,0 +1,109 @@
|
|
|
+package com.yonge.netty.server.service;
|
|
|
+
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import javax.sound.sampled.AudioFormat;
|
|
|
+
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONPath;
|
|
|
+import com.yonge.audio.analysis.AudioFloatConverter;
|
|
|
+import com.yonge.audio.analysis.detector.YINPitchDetector;
|
|
|
+import com.yonge.netty.dto.WebSocketResponse;
|
|
|
+import com.yonge.netty.server.handler.NettyChannelManager;
|
|
|
+import com.yonge.netty.server.handler.message.MessageHandler;
|
|
|
+
|
|
|
+import io.netty.channel.Channel;
|
|
|
+
|
|
|
+public class DelayCheckHandler implements MessageHandler {
|
|
|
+
|
|
|
+ private final static Logger LOGGER = LoggerFactory.getLogger(DelayCheckHandler.class);
|
|
|
+
|
|
|
+ private final static int MIN_FREQUECY = 43;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @describe 采样率
|
|
|
+ */
|
|
|
+ private float sampleRate = 44100;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每个采样大小(Bit)
|
|
|
+ */
|
|
|
+ private int bitsPerSample = 16;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通道数
|
|
|
+ */
|
|
|
+ private int channels = 1;
|
|
|
+
|
|
|
+ private boolean signed = true;
|
|
|
+
|
|
|
+ private boolean bigEndian = false;
|
|
|
+
|
|
|
+ private AudioFormat audioFormat = new AudioFormat(sampleRate, bitsPerSample, channels, signed, bigEndian);
|
|
|
+
|
|
|
+ private AudioFloatConverter converter = AudioFloatConverter.getConverter(audioFormat);
|
|
|
+
|
|
|
+ private double playTime;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private NettyChannelManager nettyChannelManager;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getAction() {
|
|
|
+ return "DELAY_CHECK";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean handleTextMessage(String userId, Channel channel, String jsonMsg) {
|
|
|
+
|
|
|
+ String command = (String) JSONPath.extract(jsonMsg, "$.header.commond");
|
|
|
+
|
|
|
+ switch (command) {
|
|
|
+ case "recordEnd":
|
|
|
+
|
|
|
+ Map<String, Object> params = new HashMap<String, Object>();
|
|
|
+ params.put("firstNoteDelayDuration", playTime);
|
|
|
+
|
|
|
+ WebSocketResponse<Map<String, Object>> resp = new WebSocketResponse<Map<String, Object>>(getAction(), params);
|
|
|
+
|
|
|
+ nettyChannelManager.sendTextMessage(userId, resp);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean handleBinaryMessage(String userId, Channel channel, byte[] bytes) {
|
|
|
+
|
|
|
+ float[] samples = new float[bytes.length / 2];
|
|
|
+
|
|
|
+ if (samples.length == 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ converter.toFloatArray(bytes, samples);
|
|
|
+
|
|
|
+ YINPitchDetector frequencyDetector = new YINPitchDetector(samples.length, audioFormat.getSampleRate());
|
|
|
+
|
|
|
+ int playFrequency = (int) frequencyDetector.getFrequency(samples);
|
|
|
+
|
|
|
+ if(playFrequency > MIN_FREQUECY) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ double durationTime = 1000 * (samples.length * 2) / audioFormat.getSampleRate() / (audioFormat.getSampleSizeInBits() / 8);
|
|
|
+
|
|
|
+ playTime += durationTime;
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|