| 
					
				 | 
			
			
				@@ -3,34 +3,43 @@ package com.yonge.nettty.dto; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.Comparator; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.List; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.concurrent.ConcurrentHashMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.util.concurrent.atomic.AtomicInteger; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.stream.Collectors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.slf4j.Logger; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.slf4j.LoggerFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import be.tarsos.dsp.AudioEvent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import be.tarsos.dsp.pitch.PitchDetectionHandler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import be.tarsos.dsp.pitch.PitchDetectionResult; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import be.tarsos.dsp.pitch.PitchDetector; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import be.tarsos.dsp.pitch.PitchProcessor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.yonge.audio.utils.ArrayUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.yonge.nettty.entity.MusicXmlBasicInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.yonge.nettty.entity.MusicXmlNote; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.yonge.nettty.entity.NoteAnalysis; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.yonge.netty.server.processor.WaveformWriter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 用户通道上下文 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public class UserChannelContext { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public class UserChannelContext implements PitchDetectionHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private final static Logger LOGGER = LoggerFactory.getLogger(UserChannelContext.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// 曲目与musicxml对应关系 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	private ConcurrentHashMap<Integer, MusicXmlBasicInfo> songMusicXmlMap = new ConcurrentHashMap<Integer, MusicXmlBasicInfo>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	private WaveformWriter waveFileProcessor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 当前音符索引 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	private AtomicInteger currentNoteIndex = new AtomicInteger(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 当前乐谱小节索引 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	private AtomicInteger currentMusicSectionIndex = new AtomicInteger(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 缓存字节数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private NoteAnalysis processingNote = new NoteAnalysis(0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	private byte[] channelBufferBytes = new byte[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	private byte[] noteBufferBytes = new byte[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private float[] handlerBufferBytes = new float[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private PitchDetector pitchDetector = PitchProcessor.PitchEstimationAlgorithm.FFT_YIN.getDetector(44100, 1024 * 4); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	public ConcurrentHashMap<Integer, MusicXmlBasicInfo> getSongMusicXmlMap() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return songMusicXmlMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -47,29 +56,20 @@ public class UserChannelContext { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		this.waveFileProcessor = waveFileProcessor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	public int incrementMusicNoteIndex() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return currentNoteIndex.incrementAndGet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	public int getCurrentMusicNoteIndex() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return currentNoteIndex.intValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public NoteAnalysis getProcessingNote() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return processingNote; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	public int incrementMusicSectionIndex() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return currentMusicSectionIndex.incrementAndGet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	public int getCurrentMusicSectionIndex() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return currentMusicSectionIndex.intValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public void setProcessingNote(NoteAnalysis processingNote) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		this.processingNote = processingNote; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	public void resetUserInfo() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		waveFileProcessor = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		currentNoteIndex.set(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		currentMusicSectionIndex.set(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		processingNote = new NoteAnalysis(0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		channelBufferBytes = new byte[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		noteBufferBytes = new byte[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		handlerBufferBytes = new float[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	public MusicXmlNote getCurrentMusicNote(Integer songId) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -83,12 +83,8 @@ public class UserChannelContext { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			musicXmlBasicInfo = songMusicXmlMap.get(songId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (musicXmlBasicInfo != null && getCurrentMusicNoteIndex() <= getTotalMusicNoteIndexNum(null)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			 * if (getCurrentMusicNoteIndex() >= musicXmlBasicInfo.getMusicXmlInfos().size()) { return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			 * musicXmlBasicInfo.getMusicXmlInfos().get(musicXmlBasicInfo.getMusicXmlInfos().size() - 1); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return musicXmlBasicInfo.getMusicXmlInfos().stream().filter(t -> t.getMusicalNotesIndex() == getCurrentMusicNoteIndex()).findFirst().get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (musicXmlBasicInfo != null && processingNote.getIndex() <= getTotalMusicNoteIndexNum(null)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return musicXmlBasicInfo.getMusicXmlInfos().stream().filter(t -> t.getMusicalNotesIndex() == processingNote.getIndex()).findFirst().get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return null; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -124,7 +120,7 @@ public class UserChannelContext { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (musicXmlBasicInfo != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return musicXmlBasicInfo.getMusicXmlInfos().stream().filter(t -> t.getMusicalNotesIndex() == getCurrentMusicSectionIndex()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return musicXmlBasicInfo.getMusicXmlInfos().stream().filter(t -> t.getMusicalNotesIndex() == processingNote.getSectionIndex()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					.sorted(Comparator.comparing(MusicXmlNote::getMusicalNotesIndex)).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -157,12 +153,107 @@ public class UserChannelContext { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		this.channelBufferBytes = channelBufferBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	public byte[] getNoteBufferBytes() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return noteBufferBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public float[] getHandlerBufferBytes() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return handlerBufferBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public void setHandlerBufferBytes(float[] handlerBufferBytes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		this.handlerBufferBytes = handlerBufferBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	public void setNoteBufferBytes(byte[] noteBufferBytes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		this.noteBufferBytes = noteBufferBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	@Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public void handlePitch(PitchDetectionResult pitchDetectionResult, AudioEvent audioEvent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		double durationTime = 1000 * (audioEvent.getFloatBuffer().length) / audioEvent.getSampleRate() / 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		float pitch = pitchDetectionResult.getPitch(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//LOGGER.info("pitch:{} timeStamp:{} endTimeStamp:{} durationTime:{}", pitch, audioEvent.getTimeStamp(), audioEvent.getEndTimeStamp(), durationTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// 获取当前音符信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		MusicXmlNote musicXmlNote = getCurrentMusicNote(null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (musicXmlNote == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//取出当前处理中的音符信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		NoteAnalysis noteAnalysis = getProcessingNote(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(noteAnalysis == null){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			noteAnalysis = new NoteAnalysis(musicXmlNote.getMusicalNotesIndex(),musicXmlNote.getMeasureIndex()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		double noteDurationTime = noteAnalysis.getDurationTime() + durationTime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		noteAnalysis.setDurationTime(noteDurationTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(pitch != -1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			noteAnalysis.setChunks(noteAnalysis.getChunks() + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			noteAnalysis.setTotalPitch(noteAnalysis.getTotalPitch() + pitch); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		setProcessingNote(noteAnalysis); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(noteAnalysis.getIndex() <= getTotalMusicNoteIndexNum(null) && noteDurationTime >= musicXmlNote.getDuration()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			noteAnalysis.setAvgPitch(noteAnalysis.getTotalPitch()/noteAnalysis.getChunks()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			LOGGER.info("当前音符下标[{}] 预计频率:{} 实际频率:{} 持续时间:{}", noteAnalysis.getIndex() , musicXmlNote.getFrequency(), noteAnalysis.getAvgPitch(), noteAnalysis.getDurationTime()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 准备处理下一个音符 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			setProcessingNote(noteAnalysis = new NoteAnalysis(musicXmlNote.getMusicalNotesIndex() + 1,musicXmlNote.getMeasureIndex())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/*// 获取字节流 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		float[] bufferBytes = audioEvent.getFloatBuffer(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// 粘合音符数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		float[] totalNoteBytes = ArrayUtil.mergeFloat(getHandlerBufferBytes(), bufferBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		setHandlerBufferBytes(totalNoteBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// 计算当前音符的数据长度 公式:数据量(字节/秒)= 采样频率(Hz)× (采样位数(bit)/ 8) × 声道数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		int length = (int) (44100 * (16 / 8) * 1 * musicXmlNote.getDuration() / 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (noteAnalysis.getIndex() <= getTotalMusicNoteIndexNum(null) && totalNoteBytes.length >= length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 处理当前音符 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			float[] noteFloatData = new float[length]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			System.arraycopy(totalNoteBytes, 0, noteFloatData, 0, length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 剩余未处理的数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			setHandlerBufferBytes(ArrayUtil.extractFloat(totalNoteBytes, length - 1, totalNoteBytes.length - 1)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 获取频率数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			float npitch = getPitch(noteFloatData, audioEvent.getBufferSize()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			LOGGER.info("第{}个音符的样本频率:{} 实际频率:{}", noteAnalysis.getIndex(), musicXmlNote.getFrequency(), npitch); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 准备处理下一个音符 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			setProcessingNote(noteAnalysis = new NoteAnalysis(musicXmlNote.getMusicalNotesIndex() + 1,musicXmlNote.getMeasureIndex())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private float getPitch(float[] audioBuffer, int bufferSize) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		int blankNum = audioBuffer.length % bufferSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		float[] zeroBytes = new float[blankNum]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		audioBuffer = ArrayUtil.mergeFloat(audioBuffer, zeroBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		int times = audioBuffer.length / bufferSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		float totalPitch = 0f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		float[] bufferByte = new float[bufferSize]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for (int i = 0; i < times; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			bufferByte = ArrayUtil.extractFloat(audioBuffer, i * bufferSize, (i + 1) * bufferSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			float pitch = pitchDetector.getPitch(bufferByte).getPitch(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(pitch == -1){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			totalPitch += pitch; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return totalPitch / times; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |