package com.darkprograms.speech.microphone; import javax.sound.sampled.AudioFileFormat; import com.darkprograms.speech.util.*; /******************************************************************************************** * Microphone Analyzer class, detects pitch and volume while extending the microphone class. * Implemented as a precursor to a Voice Activity Detection (VAD) algorithm. * Currently can be used for audio data analysis. * Dependencies: FFT.java & Complex.java. Both found in the utility package. * @author Aaron Gokaslan ********************************************************************************************/ public class MicrophoneAnalyzer extends Microphone { /** * Constructor * @param fileType The file type you want to save in. FLAC recommended. */ public MicrophoneAnalyzer(AudioFileFormat.Type fileType){ super(fileType); } /** * Gets the volume of the microphone input * Interval is 100ms so allow 100ms for this method to run in your code or specify smaller interval. * @return The volume of the microphone input or -1 if data-line is not available */ public int getAudioVolume(){ return getAudioVolume(100); } /** * Gets the volume of the microphone input * @param interval: The length of time you would like to calculate the volume over in milliseconds. * @return The volume of the microphone input or -1 if data-line is not available. */ public int getAudioVolume(int interval){ return calculateAudioVolume(this.getNumOfBytes(interval/1000d)); } /** * Gets the volume of microphone input * @param numOfBytes The number of bytes you want for volume interpretation * @return The volume over the specified number of bytes or -1 if data-line is unavailable. */ private int calculateAudioVolume(int numOfBytes){ byte[] data = getBytes(numOfBytes); if(data==null) return -1; return calculateRMSLevel(data); } /** * Calculates the volume of AudioData which may be buffered data from a data-line. * @param audioData The byte[] you want to determine the volume of * @return the calculated volume of audioData */ public static int calculateRMSLevel(byte[] audioData){ long lSum = 0; for(int i=0; imax){ max = tmp;; index = i; } } return index; } /** * Converts bytes from a TargetDataLine into a double[] allowing the information to be read. * NOTE: One byte is lost in the conversion so don't expect the arrays to be the same length! * @param bufferData The buffer read in from the target data line * @return The double[] that the buffer has been converted into. */ private double[] bytesToDoubleArray(byte[] bufferData){ final int bytesRecorded = bufferData.length; final int bytesPerSample = getAudioFormat().getSampleSizeInBits()/8; final double amplification = 100.0; // choose a number as you like double[] micBufferData = new double[bytesRecorded - bytesPerSample +1]; for (int index = 0, floatIndex = 0; index < bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) { double sample = 0; for (int b = 0; b < bytesPerSample; b++) { int v = bufferData[index + b]; if (b < bytesPerSample - 1 || bytesPerSample == 1) { v &= 0xFF; } sample += v << (b * 8); } double sample32 = amplification * (sample / 32768.0); micBufferData[floatIndex] = sample32; } return micBufferData; } }