/** * The UltrasoundAnalyzer thread class takes an array of bytes, * concatenates them into 16-bit values in little endian format, then * creates an UltrasoundDetector object to decide whether or not * the samples contain the desired frequency. The boolean decision as * to whether or not ultrasound was present in the block of samples is * sent back to the UltrasoundListener object that instantiated this * thread. * * @author Tony Offer * @author Chris Palistrant * @version 1.0 */ public class UltrasoundAnalyzer extends Thread implements Constants{ // The UltrasoundListener that this thread will notify if it // detects ultrasound in the stream of samples. protected UltrasoundListener usl = null; // The UltrasoundDetector object that this thread will use to // analyze the samples. protected UltrasoundDetector usd = null; // The byte array containing the byte samples that will be analyzed // for the presence of ultrasound. byte [] byteSamples; /** * The main UltrasoundAnalyzer constructor takes a reference to an * UltrasoundListener and a byte array containing the samples * to be analyzed. If ultrasound is detected in the byte array, the * UltrasoundListener is notified. * * @param usListener The object that will be notified of * ultrasound detections. * @param samples The byte array containing the sample values to * be analyzed for ultrasound. */ public UltrasoundAnalyzer(UltrasoundListener usListener, byte [] samples, boolean debug) { /*** TESTING ***/ //super(new Long(new java.util.Date().getTime()).toString()); usl = usListener; byteSamples = samples; // Ensure that the length of byteSamples is N*2, since // UltrasoundDetector expects exactly N samples for its // analysis. if (byteSamples.length != (N*2)) { System.out.println("UltrasoundAnalyzer: The number of bytes " + "for analysis is not N*2 where N is " + N); System.exit(1); } // Create a new UltrasoundDetector object for analyzing the // samples. Do not call UltrasoundDetector's init() method so // that construction of this object is as fast as possible. //usd = new UltrasoundDetector(SAMPLING_RATE, TARGET_FREQUENCY, // N, debug); usd = new UltrasoundDetector(SAMPLING_RATE, TARGET_FREQUENCY, N, debug); usd.init(); } /** * The UltrasoundAnalyzer thread first concatenates the array of * bytes into 16-bit little endian samples, then uses the * UltrasoundDetector to determine whether or not the samples * contain ultrasound and notifies the UltrasoundListener * accordingly. */ public void run() { // Concatenate the samples double [] samples = littleEndConcat(); // Analyze the samples and send the result back to the // UltrasoundListener that instantiated this thread. usl.analysisDone(usd.analyze(samples)); } /** * Helper method for concatenating all the values in a byte array * into 16-bit double values using the little endian format. * * @return Array of double values containing the concatenated * bytes. */ protected double [] littleEndConcat() { double [] samples = new double[byteSamples.length/2]; java.lang.Byte highOrder = null, lowOrder = null; int sample = 0; // Go through the entire byteSamples array two at a time. for (int i=0, j=0; i < byteSamples.length-1; i+=2, j++) { // Little endian means the low order byte is listed first. lowOrder = new java.lang.Byte(byteSamples[i]); highOrder = new java.lang.Byte(byteSamples[i+1]); sample = (highOrder.intValue() * 256) | (0xFF & lowOrder.intValue()); samples[j] = (double) sample; } return samples; } }