|
@@ -2,6 +2,7 @@ package com.yonge.netty.dto;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
@@ -34,6 +35,9 @@ public class UserChannelContext {
|
|
|
|
|
|
private final static Logger LOGGER = LoggerFactory.getLogger(UserChannelContext3.class);
|
|
|
|
|
|
+ //打击乐
|
|
|
+ private final static List<Integer> percussionList = Arrays.asList(23, 113);
|
|
|
+
|
|
|
private String user;
|
|
|
|
|
|
private double standardFrequecy = 442;
|
|
@@ -327,12 +331,15 @@ public class UserChannelContext {
|
|
|
//int playFrequency = (int) frequencyDetector.getFrequency(samples);
|
|
|
|
|
|
FastYin detector = new FastYin(audioFormat.getSampleRate(), samples.length);
|
|
|
- int playFrequency = (int)detector.getPitch(samples).getPitch();
|
|
|
+ int playFrequency = -1;
|
|
|
+ if(!percussionList.contains(subjectId)){
|
|
|
+ playFrequency = (int)detector.getPitch(samples).getPitch();
|
|
|
+ }
|
|
|
|
|
|
int splDb = (int) Signals.soundPressureLevel(samples);
|
|
|
int power = (int) Signals.power(samples);
|
|
|
int amplitude = (int) Signals.norm(samples);
|
|
|
- float rms = Signals.rms(samples);
|
|
|
+ //float rms = Signals.rms(samples);
|
|
|
|
|
|
double durationTime = 1000 * (samples.length * 2) / audioFormat.getSampleRate() / (audioFormat.getSampleSizeInBits() / 8);
|
|
|
|
|
@@ -361,7 +368,7 @@ public class UserChannelContext {
|
|
|
|
|
|
if (noteAnalysis.getMusicalNotesIndex() >= 0 && noteAnalysis.getMusicalNotesIndex() <= getTotalMusicNoteIndex(null)) {
|
|
|
|
|
|
- LOGGER.info("user:{} dynamicOffset:{} Frequency:{} splDb:{} Power:{} amplitude:{} rms:{} time:{}", user, dynamicOffset, playFrequency, splDb, power, amplitude, rms, playTime);
|
|
|
+ LOGGER.info("user:{} delayProcessed:{} dynamicOffset:{} Frequency:{} splDb:{} amplitude:{} time:{}", user, delayProcessed, dynamicOffset, playFrequency, splDb, amplitude, playTime);
|
|
|
|
|
|
ChunkAnalysis chunkAnalysis = new ChunkAnalysis(playTime - durationTime, playTime, playFrequency, splDb, power, amplitude);
|
|
|
|
|
@@ -372,9 +379,17 @@ public class UserChannelContext {
|
|
|
}
|
|
|
totalChunkAnalysisList.add(chunkAnalysis);
|
|
|
|
|
|
- if(delayProcessed == false && chunkAnalysis.getFrequency() > 100){
|
|
|
+ boolean flag = false;
|
|
|
+ if(percussionList.contains(subjectId)){
|
|
|
+ flag = chunkAnalysis.getAmplitude() > hardLevel.getAmplitudeThreshold();
|
|
|
+ }else{
|
|
|
+ flag = chunkAnalysis.getFrequency() > 100;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(delayProcessed == false && flag){
|
|
|
|
|
|
delayProcessed = true;
|
|
|
+
|
|
|
//计算延迟偏移值
|
|
|
//playTime = musicXmlNote.getTimeStamp() + durationTime;
|
|
|
dynamicOffset = chunkAnalysis.getStartTime() - musicXmlNote.getTimeStamp();
|
|
@@ -389,13 +404,13 @@ public class UserChannelContext {
|
|
|
noteAnalysis.setIgnore(true);
|
|
|
}
|
|
|
|
|
|
- noteAnalysis.setPlayFrequency(computeFrequency(musicXmlNote));
|
|
|
-
|
|
|
//判断节奏(音符持续时间内有不间断的音高,就节奏正确)
|
|
|
boolean tempo = true;
|
|
|
- if (subjectId == 23 || subjectId == 113) {
|
|
|
+ if (percussionList.contains(subjectId)) {
|
|
|
+ noteAnalysis.setPlayFrequency(-1);
|
|
|
tempo = computeTempoWithAmplitude2(musicXmlNote);
|
|
|
}else{
|
|
|
+ noteAnalysis.setPlayFrequency(computeFrequency(musicXmlNote));
|
|
|
tempo = computeTempoWithFrequency(musicXmlNote);
|
|
|
}
|
|
|
|
|
@@ -527,7 +542,7 @@ public class UserChannelContext {
|
|
|
|
|
|
double playDurationTime = 0;
|
|
|
|
|
|
- if (subjectId == 23 || subjectId == 113) {
|
|
|
+ if (percussionList.contains(subjectId)) {
|
|
|
if (noteAnalysis.getFrequency() == -1) {// 休止符
|
|
|
if (!noteAnalysis.isTempo()) {
|
|
|
noteAnalysis.setMusicalErrorType(NoteErrorType.CADENCE_WRONG);
|
|
@@ -581,7 +596,6 @@ public class UserChannelContext {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- LOGGER.info("[{}]演奏时长[{}]/[{}][{}] 时间[{}]-[{}]", noteAnalysis.getDurationTime(), playDurationTime, durationTime,playDurationTime * 100 / durationTime, correctedStartTime, correctedEndTime);
|
|
|
}
|
|
|
|
|
|
// 计算音分
|
|
@@ -612,7 +626,7 @@ public class UserChannelContext {
|
|
|
noteAnalysis.setIntegrityScore(integrityScore);
|
|
|
}
|
|
|
noteAnalysis.setIntonationScore(intonationScore);
|
|
|
- if (subjectId == 23 || subjectId == 113) {
|
|
|
+ if (percussionList.contains(subjectId)) {
|
|
|
noteAnalysis.setScore(tempoScore);
|
|
|
} else {
|
|
|
noteAnalysis.setScore(new BigDecimal(intonationScore + tempoScore + integrityScore).divide(new BigDecimal(3), 2).setScale(0, BigDecimal.ROUND_UP)
|
|
@@ -779,21 +793,24 @@ public class UserChannelContext {
|
|
|
|
|
|
List<ChunkAnalysis> chunkAnalysisList = totalChunkAnalysisList.stream().filter(t -> Double.doubleToLongBits(t.getStartTime()) >= Double.doubleToLongBits(startTime) && Double.doubleToLongBits(t.getEndTime()) <= Double.doubleToLongBits(endTime)).collect(Collectors.toList());
|
|
|
|
|
|
- /*double correctedStartTime = queryFirstNoteStartTime(chunkAnalysisList, musicXmlNote);
|
|
|
+ double correctedStartTime = queryFirstNoteStartTime(chunkAnalysisList, musicXmlNote);
|
|
|
double correctedEndTime = correctedStartTime + musicXmlNote.getDuration();
|
|
|
|
|
|
chunkAnalysisList = totalChunkAnalysisList.stream().filter(t -> Double.doubleToLongBits(t.getStartTime()) >= Double.doubleToLongBits(correctedStartTime) && Double.doubleToLongBits(t.getEndTime()) <= Double.doubleToLongBits(correctedEndTime)).collect(Collectors.toList());
|
|
|
- */
|
|
|
+
|
|
|
if(chunkAnalysisList == null || chunkAnalysisList.size() == 0){
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
+ ChunkAnalysis firstChunkAnalysis = chunkAnalysisList.get(0);
|
|
|
+
|
|
|
+ LOGGER.info("-------startTime:{} endTime:{}------", firstChunkAnalysis.getStartTime(), chunkAnalysisList.get(chunkAnalysisList.size() - 1)
|
|
|
+ .getEndTime());
|
|
|
|
|
|
if (musicXmlNote.getFrequency() == -1) {// 休止符
|
|
|
return chunkAnalysisList.stream().filter(t -> t.getAmplitude() > hardLevel.getAmplitudeThreshold()).count() <= 0;
|
|
|
}
|
|
|
|
|
|
- ChunkAnalysis firstChunkAnalysis = chunkAnalysisList.get(0);
|
|
|
-
|
|
|
Optional<ChunkAnalysis> chunkAnalysisOptional = totalChunkAnalysisList.stream().filter(t -> Double.doubleToLongBits(t.getEndTime()) == Double.doubleToLongBits(firstChunkAnalysis.getStartTime())).findFirst();
|
|
|
|
|
|
ChunkAnalysis lastChunkAnalysis = null;
|
|
@@ -808,13 +825,15 @@ public class UserChannelContext {
|
|
|
|
|
|
chunkAmplitudeList.add(0, lastChunkAnalysis.getAmplitude());
|
|
|
|
|
|
+ LOGGER.info("--Amplitude:{} Denominator:{}",chunkAmplitudeList.stream().map(t -> t).collect(Collectors.toList()), musicXmlNote.getDenominator());
|
|
|
+
|
|
|
// 检测是否有多个波峰
|
|
|
boolean tempo = false;
|
|
|
boolean isContinue = true;
|
|
|
int firstPeakIndex = -1;
|
|
|
int peakSize = 0;
|
|
|
for (int i = 1; i < chunkAmplitudeList.size(); i++) {
|
|
|
- if (chunkAmplitudeList.get(i) > hardLevel.getAmplitudeThreshold() && chunkAmplitudeList.get(i) > chunkAmplitudeList.get(i - 1) + 2) {
|
|
|
+ if (chunkAmplitudeList.get(i) > hardLevel.getAmplitudeThreshold() && chunkAmplitudeList.get(i) > chunkAmplitudeList.get(i - 1) + 1) {
|
|
|
tempo = true;
|
|
|
if(firstPeakIndex == -1){
|
|
|
firstPeakIndex = i;
|
|
@@ -857,6 +876,15 @@ public class UserChannelContext {
|
|
|
return musicXmlNote.getTimeStamp() + dynamicOffset;
|
|
|
}
|
|
|
|
|
|
+ if (percussionList.contains(subjectId)) {
|
|
|
+ Optional<ChunkAnalysis> optional = chunkAnalysisList.stream().filter(t -> t.getAmplitude() > hardLevel.getAmplitudeThreshold()).findFirst();
|
|
|
+ if(optional.isPresent()){
|
|
|
+ return optional.get().getStartTime();
|
|
|
+ }else{
|
|
|
+ return musicXmlNote.getTimeStamp() + dynamicOffset;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
//判断是否与上一个音是同一个音符
|
|
|
if(musicXmlNote.getMusicalNotesIndex() > 0){
|
|
|
MusicXmlNote preMusicXmlNote = getCurrentMusicNote(null, musicXmlNote.getMusicalNotesIndex() - 1);
|