Android Open Source - audiopulse-androidclient A Pulse Iface






From Project

Back to project page audiopulse-androidclient.

License

The source code is released under:

GNU General Public License

If you think the Android project audiopulse-androidclient listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.audiopulse.hardware;
//from  w  w  w .  java 2  s  . c  o m
import android.app.Activity;
import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;


/**
 * Created by ben on 1/3/14.
 */
public class APulseIface {
  private static final String TAG="APulseIface";
    public APulseIface(Activity activity) {
        this.usb = new USBIface(activity);
        buffer = ByteBuffer.allocateDirect(64);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
    }

    public int connect(USBIface.USBConnHandler handler){
        return usb.connect(handler);
    }

    public APulseStatus getStatus(){
        usb.receive(buffer.array(), 5);
        return new APulseStatus(buffer);
    }

    /*!
     @brief Reset the device and wait for it to confirm
     */
    public void reset(){
        APulseStatus status;
        buffer.array()[0] = CMD_RESET;
        usb.send(buffer.array(), 1);
        do{
            status = getStatus();
        } while(!((status.test_state == APulseStatus.TEST_RESET) &&
                  (status.wg_state == APulseStatus.WG_RESET) &&
                  (status.in_state == APulseStatus.IN_RESET)));
    }

    /*!
     @brief Get PSD and average data from device

     @note This MUST be preceded by a getStatus call confirming that all captures are done
     */
    public APulseData getData(){
        APulseData data = new APulseData();
        buffer.array()[0] = CMD_GETDATA;
        usb.send(buffer.array(), 1);
        // Initially read 64
        int len = 64;
        while(len != 0){
            usb.receive(buffer.array(), len);
            len = data.pushBuffer(buffer);
        }
        return data;
    }

    public void configTones(ToneConfig[] tones){
        buffer.position(0);
        buffer.put((byte)CMD_SETUPTONES);
        for(int i = 0; i < 3; i++){
            if(tones.length > i){
                tones[i].toBuffer(buffer);
            } else {
                ToneOff t = new ToneOff();
                t.toBuffer(buffer);
            }
        }
        buffer.position(0);
        usb.send(buffer.array(), 35);
    }

    public void configCapture(int t1, int overlap, int nframes){
        buffer.position(0);
        buffer.put((byte) CMD_SETUPCAPTURE);
        buffer.putShort((short) overlap);
        buffer.put((byte) 0); //window function, ignore it
        buffer.putShort((short) nframes);
        buffer.putShort((short) t1);
        buffer.position(0);
        usb.send(buffer.array(), 63);
    }

    public void start(){
        buffer.position(0);
        buffer.put((byte)CMD_START);

        buffer.position(0);
        usb.send(buffer.array(), 63);
    }

    /*!
     @brief A convenient access class for a returned status code
     */
    static public class APulseStatus {
        public APulseStatus(ByteBuffer buffer){
            version = (int)buffer.get(0) & 0xFF;
            in_state = (int)buffer.get(1) & 0xFF;
            wg_state = (int)buffer.get(2) & 0xFF;
            test_state = (int)buffer.get(3) & 0xFF;
            err_code = (int)buffer.get(4) & 0xFF;
        }

        public int version;
        public int wg_state;
        public int in_state;
        public int test_state;
        public int err_code;

        public static final int WG_RESET   = 0;
        public static final int WG_READY   = 1;
        public static final int WG_RUNNING = 2;
        public static final int WG_DONE    = 3;

        public static final int IN_RESET     = 0;
        public static final int IN_READY     = 1;
        public static final int IN_RUNWAIT   = 2;
        public static final int IN_CAPTURING = 3;
        public static final int IN_DONE      = 4;

        public static final int TEST_RESET       = 0;
        public static final int TEST_CONFIGURING = 1;
        public static final int TEST_READY       = 2;
        public static final int TEST_RUNNING     = 3;
        public static final int TEST_DONE        = 4;


        public String wgStateString(){
            switch(wg_state){
                case WG_RESET:
                    return "reset";
                case WG_READY:
                    return "ready";
                case WG_RUNNING:
                    return "running";
                case WG_DONE:
                    return "done";
                default:
                    return "unknown";
            }
        }

        public String testStateString(){
            switch(test_state){
                case TEST_RESET:
                    return "reset";
                case TEST_CONFIGURING:
                    return "configuring";
                case TEST_READY:
                    return "ready";
                case TEST_RUNNING:
                    return "running";
                case TEST_DONE:
                    return "done";
                default:
                    return "unknown";
            }
        }

        public String inStateString(){
            switch(in_state){
                case IN_RESET:
                    return "reset";
                case IN_READY:
                    return "ready";
                case IN_RUNWAIT:
                    return "runwait";
                case IN_CAPTURING:
                    return "capturing";
                case IN_DONE:
                    return "done";
                default:
                    return "unknown";
            }
        }
    }

    /*!
     @brief A representation of data from the embedded device which also provides
        parsing facilities
     */
    static public class APulseData {
        public APulseData() {
            frame_count = 0;
            average = new int[APulseIface.transform_len];
            psd = new int[APulseIface.transform_len / 2 + 1];
        }

        /*!
         @brief Apply a new received buffer
         @param buffer The received buffer
         @return The number of bytes to receive for the next frame

         @note Call pushBuffer until it returns 0
         */
        public int pushBuffer(ByteBuffer buffer){
            int ret;
            buffer.position(0);

            if(frame_count < psd_frames - 1){
                for(int i = 0; i < 16; i++){
                    psd[frame_count * 16 + i] = buffer.getInt();//iBuffer.get(i);
                }
                // Check if the next one is the wuss-frame (one sample)
                if(frame_count == psd_frames - 2){
                    ret = 4;
                } else {
                    ret = 64;
                }
            } else if (frame_count == psd_frames - 1){
                // This is the last PSD frame, containing only one sample
                psd[frame_count * 16] = buffer.getInt();//iBuffer.get(0);
                ret = 64;
            } else if (frame_count - psd_frames < average_frames){
                // Now receiving average frames
                for(int i = 0; i < 16; i++){
                    average[(frame_count - psd_frames)* 16 + i] = buffer.getInt();//iBuffer.get(i);
                }
                // Check if last frame
                if(frame_count - psd_frames == average_frames - 1)
                    ret = 0;
                else
                    ret = 64;
            } else {
                // Why are we here?
                ret = 0;
            }

            frame_count += 1;

            return ret;
        }

        //public final int[] getPSD(){return psd;}
        //public final int[] getAverage(){return average;}
        public double[] getPSD(){
          
            double[] ret = new double[APulseIface.transform_len / 2 + 1];
            for(int i = 0; i < APulseIface.transform_len / 2 + 1; i++){
              //Normalize the FFT values by 1.518497877336946e+09
              //which is the RMS of a sine wave with peak-to-peak level of 2^31
              //So that a maximum sine wave in record by the mic should give
              //0 dB value
              //Because power for a pure tone peak-to-peak level of 2^31 should 
              //be sqrt(2)(2^31)
                ret[i] = ((double)psd[i])/3037000499.97605;
                ret[i]=(ret[i] == 0) ? -Double.NEGATIVE_INFINITY : 10.0*Math.log10(ret[i]); 
            }
            return ret;
        }

        public double[] getAverage(){
            double[] ret = new double[APulseIface.transform_len];
            for(int i = 0; i < APulseIface.transform_len; i++){
                ret[i] = ((double)average[i]) / (double)0x7FFFFFFF;
            }
            return ret;
        }

        private int frame_count;
        private int average[];
        private int psd[];

        private static final int psd_frames =
                (int)Math.ceil((float)(APulseIface.transform_len / 2 + 1) / 16);
        private static final int average_frames =
                (int)((APulseIface.transform_len) / 16);
    }

    public static class ToneConfig {
        public void toBuffer(ByteBuffer buffer){
            buffer.put((byte)((ch << 4) | tone));
            buffer.putShort((short)(db * (float)(1 << 8)));
            buffer.putShort((short)f1);
            buffer.putShort((short)f2);
            buffer.putShort((short)t1);
            buffer.putShort((short)t2);
        }

        protected int tone;
        protected int f1;
        protected int f2;
        protected int t1;
        protected int t2;
        protected double db;
        protected int ch;
    }

    public static class FixedTone extends ToneConfig {
        public FixedTone(int f1, int t1, int t2, double db, int ch){
            this.tone = TONE_FIXED;
            this.f1 = f1;
            this.f2 = f1;
            this.t1 = t1;
            this.t2 = t2;
            this.db = db;
            this.ch = ch;
        }

    }

    public static class ChirpTone extends ToneConfig {
        public ChirpTone(int f1, int f2, int t1, int t2, double db, int ch){
            this.tone = TONE_CHIRP;
            this.f1 = f1;
            this.f2 = f2;
            this.t1 = t1;
            this.t2 = t2;
            this.db = db;
            this.ch = ch;
        }
    }

    public class ToneOff extends ToneConfig {
        public ToneOff(){
            this.tone = TONE_OFF;
        }
    }

    public static final int transform_len = 512;

    private ByteBuffer buffer;

    public USBIface usb;

    private static final int CMD_RESET        = 0;
    private static final int CMD_STARTUP      = 1;
    private static final int CMD_SETUPTONES   = 2;
    private static final int CMD_SETUPCAPTURE = 3;
    private static final int CMD_GETSTATUS    = 4;
    private static final int CMD_GETDATA      = 5;
    private static final int CMD_START        = 6;

    private static final int TONE_OFF         = 0;
    private static final int TONE_FIXED       = 1;
    private static final int TONE_CHIRP       = 2;
}




Java Source Code List

org.audiopulse.activities.AudioPulseActivity.java
org.audiopulse.activities.MonitorHandler.java
org.audiopulse.activities.MonitorThread.java
org.audiopulse.activities.PlotSpectralActivity.java
org.audiopulse.activities.TestEarActivity.java
org.audiopulse.activities.UsbTestActivity.java
org.audiopulse.analysis.DPOAEAnalyzer.java
org.audiopulse.analysis.DPOAEResults.java
org.audiopulse.analysis.SignalProcessing.java
org.audiopulse.analysis.SpectralWindows.java
org.audiopulse.graphics.DemoView.java
org.audiopulse.graphics.PlotSpectralView.java
org.audiopulse.hardware.APulseIface.java
org.audiopulse.hardware.USBIface.java
org.audiopulse.io.AudioPulseFilePackager.java
org.audiopulse.io.AudioPulseFileWriter.java
org.audiopulse.io.UsbAudioEmulator.java
org.audiopulse.io.UsbAudioInterface.java