|
@@ -6,37 +6,34 @@ import be.tarsos.dsp.AudioProcessor;
|
|
|
import be.tarsos.dsp.SilenceDetector;
|
|
|
import be.tarsos.dsp.beatroot.BeatRootOnsetEventHandler;
|
|
|
import be.tarsos.dsp.io.PipedAudioStream;
|
|
|
-import be.tarsos.dsp.io.TarsosDSPAudioFormat;
|
|
|
import be.tarsos.dsp.io.TarsosDSPAudioInputStream;
|
|
|
import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
|
|
|
import be.tarsos.dsp.onsets.ComplexOnsetDetector;
|
|
|
import be.tarsos.dsp.onsets.OnsetHandler;
|
|
|
-import com.alibaba.fastjson.JSON;
|
|
|
+import com.ym.mec.biz.dal.dao.SysMusicScoreAccompanimentDao;
|
|
|
import com.ym.mec.biz.dal.dao.SysMusicScoreDao;
|
|
|
import com.ym.mec.biz.dal.entity.SysMusicScore;
|
|
|
+import com.ym.mec.biz.dal.entity.SysMusicScoreAccompaniment;
|
|
|
import com.ym.mec.biz.service.SoundService;
|
|
|
import com.ym.mec.common.constant.CommonConstants;
|
|
|
import com.ym.mec.common.controller.BaseController;
|
|
|
import com.ym.mec.common.entity.HttpResponseResult;
|
|
|
import com.ym.mec.common.exception.BizException;
|
|
|
+import com.ym.mec.common.service.IdGeneratorService;
|
|
|
import org.apache.commons.io.FileUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
-import javax.sound.sampled.AudioFileFormat;
|
|
|
import javax.sound.sampled.AudioFormat;
|
|
|
-import javax.sound.sampled.AudioSystem;
|
|
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
|
|
import java.io.File;
|
|
|
-import java.io.FileOutputStream;
|
|
|
import java.io.IOException;
|
|
|
-import java.io.InputStream;
|
|
|
import java.math.BigDecimal;
|
|
|
-import java.net.MalformedURLException;
|
|
|
import java.net.URL;
|
|
|
-import java.net.URLConnection;
|
|
|
import java.util.*;
|
|
|
|
|
|
/**
|
|
@@ -46,10 +43,16 @@ import java.util.*;
|
|
|
@Service
|
|
|
public class SoundServiceImpl implements SoundService {
|
|
|
|
|
|
+ private final Logger LOGGER = LoggerFactory.getLogger(SoundServiceImpl.class);
|
|
|
+
|
|
|
private float sampleRate = 44100;
|
|
|
|
|
|
@Autowired
|
|
|
private SysMusicScoreDao sysMusicScoreDao;
|
|
|
+ @Autowired
|
|
|
+ private SysMusicScoreAccompanimentDao sysMusicScoreAccompanimentDao;
|
|
|
+ @Autowired
|
|
|
+ private IdGeneratorService idGeneratorService;
|
|
|
|
|
|
/**
|
|
|
* @describe 音频节拍信息提取
|
|
@@ -57,7 +60,7 @@ public class SoundServiceImpl implements SoundService {
|
|
|
* @date 2021/5/19 0019
|
|
|
* @return
|
|
|
*/
|
|
|
- private List<Double> beatExtractor(byte[] bytes, String url) throws UnsupportedAudioFileException, IOException {
|
|
|
+ private List<Double> beatExtractor(byte[] bytes, String url) throws UnsupportedAudioFileException {
|
|
|
List<Double> times = new ArrayList<>();
|
|
|
int size = 256;
|
|
|
int overlap = 128;
|
|
@@ -86,7 +89,7 @@ public class SoundServiceImpl implements SoundService {
|
|
|
* @param bytes: 文件字节
|
|
|
* @return java.util.List<java.lang.Double>
|
|
|
*/
|
|
|
- private List<Double> soundPressureLevelExtractor(byte[] bytes, String url, BigDecimal duration) throws UnsupportedAudioFileException, IOException {
|
|
|
+ private List<Double> soundPressureLevelExtractor(byte[] bytes, String url) throws UnsupportedAudioFileException {
|
|
|
List<Double> pitchs = new ArrayList<>();
|
|
|
int size = 2048;
|
|
|
int overlap = 0;
|
|
@@ -108,7 +111,7 @@ public class SoundServiceImpl implements SoundService {
|
|
|
}
|
|
|
});
|
|
|
dispatcher.run();
|
|
|
- duration = new BigDecimal(t[0]);
|
|
|
+ pitchs.add(t[0]);
|
|
|
return pitchs;
|
|
|
}
|
|
|
|
|
@@ -118,7 +121,7 @@ public class SoundServiceImpl implements SoundService {
|
|
|
return dispatcher;
|
|
|
}
|
|
|
|
|
|
- private AudioDispatcher getFromFile(String url, int size, int overlap) throws UnsupportedAudioFileException, IOException {
|
|
|
+ private AudioDispatcher getFromFile(String url, int size, int overlap) {
|
|
|
PipedAudioStream file = new PipedAudioStream(url);
|
|
|
TarsosDSPAudioInputStream stream = file.getMonoStream(44100,0);
|
|
|
|
|
@@ -138,62 +141,90 @@ public class SoundServiceImpl implements SoundService {
|
|
|
BigDecimal intonation = BigDecimal.ZERO;
|
|
|
BigDecimal cadence = BigDecimal.ZERO;
|
|
|
BigDecimal integrity = BigDecimal.ZERO;
|
|
|
-
|
|
|
+ File f = null;
|
|
|
+ File f_r = null;
|
|
|
try {
|
|
|
URL url = new URL(sysMusicScore.getUrl());
|
|
|
- String filePath = FileUtils.getTempDirectoryPath()+ System.currentTimeMillis() + ".mp3";
|
|
|
- File f = new File(filePath);
|
|
|
+ String filePath = FileUtils.getTempDirectoryPath()+ idGeneratorService.generatorId("sound") + ".mp3";
|
|
|
+ f = new File(filePath);
|
|
|
FileUtils.copyURLToFile(url, f);
|
|
|
|
|
|
+ LOGGER.info("文件名:{},伴奏编号:{},源文件:{}", record.getOriginalFilename(), musicScoreId, filePath);
|
|
|
+
|
|
|
BigDecimal oneHandred = new BigDecimal(100);
|
|
|
|
|
|
BigDecimal l_s = new BigDecimal(0);
|
|
|
BigDecimal l_r = new BigDecimal(0);
|
|
|
|
|
|
+ String filePath_r = FileUtils.getTempDirectoryPath()+ idGeneratorService.generatorId("sound") + ".mp3";
|
|
|
+ f_r = new File(filePath_r);
|
|
|
+ FileUtils.copyToFile(record.getInputStream(), f_r);
|
|
|
+
|
|
|
//相似度
|
|
|
- List<Double> pitchs_s = soundPressureLevelExtractor(null, filePath, l_s);
|
|
|
- List<Double> pitchs_r = soundPressureLevelExtractor(record.getBytes(), null, l_r);
|
|
|
+ List<Double> pitchs_s = soundPressureLevelExtractor(null, filePath);
|
|
|
+// List<Double> pitchs_r = soundPressureLevelExtractor(record.getBytes(), null);
|
|
|
+ List<Double> pitchs_r = soundPressureLevelExtractor(null, filePath_r);
|
|
|
|
|
|
int maxLength = pitchs_s.size();
|
|
|
if(pitchs_r.size()<maxLength){
|
|
|
maxLength = pitchs_r.size();
|
|
|
}
|
|
|
|
|
|
- Double pitchSize = Double.valueOf(0);
|
|
|
- Double allPitchGap = Double.valueOf(0);
|
|
|
+ if(maxLength>0){
|
|
|
+ l_s = new BigDecimal(pitchs_s.get(pitchs_s.size() - 1));
|
|
|
+ pitchs_s.remove(pitchs_s.size() - 1);
|
|
|
+ l_r = new BigDecimal(pitchs_r.get(pitchs_r.size() - 1));
|
|
|
+ pitchs_r.remove(pitchs_r.size() - 1);
|
|
|
+ maxLength = maxLength-1;
|
|
|
+ }
|
|
|
+
|
|
|
+ double pitchSize = 0;
|
|
|
+ double allPitchGap = 0;
|
|
|
for(int i=0;i<maxLength;i++){
|
|
|
- Double pitch1 = Math.abs(pitchs_s.get(i));
|
|
|
- Double pitch2 = Math.abs(pitchs_r.get(i));
|
|
|
- Double pitchGap = Math.abs(pitch1-pitch2);
|
|
|
+ double pitch1 = Math.abs(pitchs_s.get(i));
|
|
|
+ double pitch2 = Math.abs(pitchs_r.get(i));
|
|
|
+ double pitchGap = Math.abs(pitch1-pitch2);
|
|
|
if(pitchGap>pitch1){
|
|
|
pitchGap = pitch1;
|
|
|
}
|
|
|
allPitchGap+=pitchGap;
|
|
|
pitchSize+=pitch1;
|
|
|
}
|
|
|
- Double intonation_d = 1-(allPitchGap/pitchSize);
|
|
|
+ double intonation_d = 0;
|
|
|
+ if(pitchSize>0){
|
|
|
+ intonation_d = 1-(allPitchGap/pitchSize);
|
|
|
+ }
|
|
|
intonation = new BigDecimal(intonation_d).multiply(oneHandred).setScale(0, BigDecimal.ROUND_HALF_UP);
|
|
|
|
|
|
//节奏
|
|
|
List<Double> times_s = beatExtractor(null, filePath);
|
|
|
- List<Double> times_r = beatExtractor(record.getBytes(), null);
|
|
|
+// List<Double> times_r = beatExtractor(record.getBytes(), null);
|
|
|
+ List<Double> times_r = beatExtractor(null, filePath_r);
|
|
|
|
|
|
float sameTimes = 0;
|
|
|
for (Double time1 : times_s) {
|
|
|
for (Double time2 : times_r) {
|
|
|
- if(Math.abs(time2-time1)<0.1){
|
|
|
+ if(Math.abs(time2-time1)<1.5){
|
|
|
sameTimes++;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- Double cadence_d = Double.valueOf(sameTimes/times_s.size());
|
|
|
+ double cadence_d = 0;
|
|
|
+ if (times_r.size()>0){
|
|
|
+ cadence_d = sameTimes/times_r.size();
|
|
|
+ }
|
|
|
cadence = new BigDecimal(cadence_d).multiply(oneHandred).setScale(0, BigDecimal.ROUND_HALF_UP);
|
|
|
- System.out.printf("节奏:%.2f", cadence);
|
|
|
|
|
|
- integrity = new BigDecimal(1);
|
|
|
- if(l_r.compareTo(l_s)<0){
|
|
|
- integrity = l_r.divide(l_s, 0, BigDecimal.ROUND_HALF_UP);
|
|
|
+ integrity = new BigDecimal(0);
|
|
|
+ if(l_r.compareTo(BigDecimal.ZERO)<=0||l_s.compareTo(BigDecimal.ZERO)<=0){
|
|
|
+
|
|
|
+ }else if(l_r.compareTo(l_s)<0){
|
|
|
+ integrity = l_r.divide(l_s, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_HALF_UP).multiply(oneHandred).setScale(0, BigDecimal.ROUND_HALF_UP);
|
|
|
+ }else{
|
|
|
+ integrity = new BigDecimal(100);
|
|
|
}
|
|
|
+ integrity = integrity;
|
|
|
|
|
|
score = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), 0, BigDecimal.ROUND_HALF_UP);
|
|
|
|
|
@@ -202,9 +233,15 @@ public class SoundServiceImpl implements SoundService {
|
|
|
e.printStackTrace();
|
|
|
} catch (IOException e) {
|
|
|
e.printStackTrace();
|
|
|
+ }finally {
|
|
|
+ if(f!=null){
|
|
|
+ f.delete();
|
|
|
+ }
|
|
|
+ if(f_r!=null){
|
|
|
+ f_r.delete();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
result.put("score", score);
|
|
|
result.put("intonation", intonation);
|
|
|
result.put("cadence", cadence);
|