AudioEvent.java (6135B)
1 /* 2 * _______ _____ _____ _____ 3 * |__ __| | __ \ / ____| __ \ 4 * | | __ _ _ __ ___ ___ ___| | | | (___ | |__) | 5 * | |/ _` | '__/ __|/ _ \/ __| | | |\___ \| ___/ 6 * | | (_| | | \__ \ (_) \__ \ |__| |____) | | 7 * |_|\__,_|_| |___/\___/|___/_____/|_____/|_| 8 * 9 * ------------------------------------------------------------- 10 * 11 * TarsosDSP is developed by Joren Six at IPEM, University Ghent 12 * 13 * ------------------------------------------------------------- 14 * 15 * Info: http://0110.be/tag/TarsosDSP 16 * Github: https://github.com/JorenSix/TarsosDSP 17 * Releases: http://0110.be/releases/TarsosDSP/ 18 * 19 * TarsosDSP includes modified source code by various authors, 20 * for credits and info, see README. 21 * 22 */ 23 24 25 package be.tarsos.dsp; 26 27 import java.util.Arrays; 28 29 import be.tarsos.dsp.io.TarsosDSPAudioFloatConverter; 30 import be.tarsos.dsp.io.TarsosDSPAudioFormat; 31 32 /** 33 * An audio event flows through the processing pipeline. The object is reused for performance reasons. 34 * The arrays with audio information are also reused, so watch out when using the buffer getter and setters. 35 * 36 * @author Joren Six 37 */ 38 public class AudioEvent { 39 /** 40 * The format specifies a particular arrangement of data in a sound stream. 41 */ 42 private final TarsosDSPAudioFormat format; 43 44 private final TarsosDSPAudioFloatConverter converter; 45 46 /** 47 * The audio data encoded in floats from -1.0 to 1.0. 48 */ 49 private float[] floatBuffer; 50 51 /** 52 * The audio data encoded in bytes according to format. 53 */ 54 private byte[] byteBuffer; 55 56 /** 57 * The overlap in samples. 58 */ 59 private int overlap; 60 61 /** 62 * The length of the stream, expressed in sample frames rather than bytes 63 */ 64 private long frameLength; 65 66 /** 67 * The number of bytes processed before this event. It can be used to calculate the time stamp for when this event started. 68 */ 69 private long bytesProcessed; 70 71 private int bytesProcessing; 72 73 74 public AudioEvent(TarsosDSPAudioFormat format){ 75 this.format = format; 76 this.converter = TarsosDSPAudioFloatConverter.getConverter(format); 77 this.overlap = 0; 78 } 79 80 public float getSampleRate(){ 81 return format.getSampleRate(); 82 } 83 84 public int getBufferSize(){ 85 return getFloatBuffer().length; 86 } 87 88 /** 89 * @return The length of the stream, expressed in sample frames rather than bytes 90 */ 91 public long getFrameLength(){ 92 return frameLength; 93 } 94 95 public int getOverlap(){ 96 return overlap; 97 } 98 99 public void setOverlap(int newOverlap){ 100 overlap = newOverlap; 101 } 102 103 public void setBytesProcessed(long bytesProcessed){ 104 this.bytesProcessed = bytesProcessed; 105 } 106 107 /** 108 * Calculates and returns the time stamp at the beginning of this audio event. 109 * @return The time stamp at the beginning of the event in seconds. 110 */ 111 public double getTimeStamp(){ 112 return bytesProcessed / format.getFrameSize() / format.getSampleRate(); 113 } 114 115 public double getEndTimeStamp(){ 116 return(bytesProcessed + bytesProcessing) / format.getFrameSize() / format.getSampleRate(); 117 } 118 119 public long getSamplesProcessed(){ 120 return bytesProcessed / format.getFrameSize(); 121 } 122 123 /** 124 * Calculate the progress in percentage of the total number of frames. 125 * 126 * @return a percentage of processed frames or a negative number if the 127 * number of frames is not known beforehand. 128 */ 129 public double getProgress(){ 130 return bytesProcessed / format.getFrameSize() / (double) frameLength; 131 } 132 133 /** 134 * Return a byte array with the audio data in bytes. 135 * A conversion is done from float, cache accordingly on the other side... 136 * 137 * @return a byte array with the audio data in bytes. 138 */ 139 public byte[] getByteBuffer(){ 140 int length = getFloatBuffer().length * format.getFrameSize(); 141 if(byteBuffer == null || byteBuffer.length != length){ 142 byteBuffer = new byte[length]; 143 } 144 converter.toByteArray(getFloatBuffer(), byteBuffer); 145 return byteBuffer; 146 } 147 148 public void setFloatBuffer(float[] floatBuffer) { 149 this.floatBuffer = floatBuffer; 150 } 151 152 public float[] getFloatBuffer(){ 153 return floatBuffer; 154 } 155 156 /** 157 * Calculates and returns the root mean square of the signal. Please 158 * cache the result since it is calculated every time. 159 * @return The <a 160 * href="http://en.wikipedia.org/wiki/Root_mean_square">RMS</a> of 161 * the signal present in the current buffer. 162 */ 163 public double getRMS() { 164 return calculateRMS(floatBuffer); 165 } 166 167 168 /** 169 * Returns the dBSPL for a buffer. 170 * 171 * @return The dBSPL level for the buffer. 172 */ 173 public double getdBSPL() { 174 return soundPressureLevel(floatBuffer); 175 } 176 177 /** 178 * Calculates and returns the root mean square of the signal. Please 179 * cache the result since it is calculated every time. 180 * @param floatBuffer The audio buffer to calculate the RMS for. 181 * @return The <a 182 * href="http://en.wikipedia.org/wiki/Root_mean_square">RMS</a> of 183 * the signal present in the current buffer. 184 */ 185 public static double calculateRMS(float[] floatBuffer){ 186 double rms = 0.0; 187 for (int i = 0; i < floatBuffer.length; i++) { 188 rms += floatBuffer[i] * floatBuffer[i]; 189 } 190 rms = rms / Double.valueOf(floatBuffer.length); 191 rms = Math.sqrt(rms); 192 return rms; 193 } 194 195 public void clearFloatBuffer() { 196 Arrays.fill(floatBuffer, 0); 197 } 198 199 /** 200 * Returns the dBSPL for a buffer. 201 * 202 * @param buffer 203 * The buffer with audio information. 204 * @return The dBSPL level for the buffer. 205 */ 206 private static double soundPressureLevel(final float[] buffer) { 207 double rms = calculateRMS(buffer); 208 return linearToDecibel(rms); 209 } 210 211 /** 212 * Converts a linear to a dB value. 213 * 214 * @param value 215 * The value to convert. 216 * @return The converted value. 217 */ 218 private static double linearToDecibel(final double value) { 219 return 20.0 * Math.log10(value); 220 } 221 222 public boolean isSilence(double silenceThreshold) { 223 return soundPressureLevel(floatBuffer) < silenceThreshold; 224 } 225 226 public void setBytesProcessing(int bytesProcessing) { 227 this.bytesProcessing = bytesProcessing; 228 229 } 230 231 }