/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.cts.verifier.audio;

import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
import com.android.cts.verifier.audio.wavelib.*;
import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;

import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.AudioRecord;
import android.media.MediaRecorder;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;

import android.util.Log;

import android.view.View;
import android.view.View.OnClickListener;

import android.widget.Button;
import android.widget.TextView;
import android.widget.SeekBar;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

/**
 * Tests Audio built in Microphone response using external speakers and USB reference microphone.
 */
public class AudioFrequencyMicActivity extends PassFailButtons.Activity implements Runnable,
    AudioRecord.OnRecordPositionUpdateListener {
    private static final String TAG = "AudioFrequencyMicActivity";

    private static final int TEST_STARTED = 900;
    private static final int TEST_ENDED = 901;
    private static final int TEST_MESSAGE = 902;
    private static final int TEST1_MESSAGE = 903;
    private static final int TEST1_ENDED = 904;
    private static final double MIN_ENERGY_BAND_1 = -50.0;          //dB Full Scale
    private static final double MAX_ENERGY_BAND_1_BASE = -60.0;     //dB Full Scale
    private static final double MIN_FRACTION_POINTS_IN_BAND = 0.3;
    private static final double MAX_VAL = Math.pow(2, 15);
    private static final double CLIP_LEVEL = (MAX_VAL-10) / MAX_VAL;

    final OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
    Context mContext;

    Button mSpeakersReady;              //user signal to have connected external speakers
    Button mTest1Button;                //execute test 1
    Button mUsbMicReady;          //user signal to have connected USB Microphone
    Button mTest2Button;                 //user to start test
    String mUsbDevicesInfo;             //usb device info for report
    LinearLayout mLayoutTest1;
    LinearLayout mLayoutTest2a;
    LinearLayout mLayoutTest2b;

    TextView mSpeakerReadyText;
    TextView mTest2Result;
    TextView mUsbStatusText;
    TextView mTest1Result;
    ProgressBar mProgressBar;

    private boolean mIsRecording = false;
    private final Object mRecordingLock = new Object();
    private AudioRecord mRecorder;
    private int mMinRecordBufferSizeInSamples = 0;
    private short[] mAudioShortArray;
    private short[] mAudioShortArray2;

    private final int mBlockSizeSamples = 1024;
    private final int mSamplingRate = 48000;
    private final int mSelectedRecordSource = MediaRecorder.AudioSource.VOICE_RECOGNITION;
    private final int mChannelConfig = AudioFormat.CHANNEL_IN_MONO;
    private final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
    private Thread mRecordThread;

    PipeShort mPipe = new PipeShort(65536);
    SoundPlayerObject mSPlayer;

    private DspBufferComplex mC;
    private DspBufferDouble mData;

    private DspWindow mWindow;
    private DspFftServer mFftServer;
    private VectorAverage mFreqAverageMain = new VectorAverage();

    private VectorAverage mFreqAverageBase = new VectorAverage();
    private VectorAverage mFreqAverageBuiltIn = new VectorAverage();
    private VectorAverage mFreqAverageReference = new VectorAverage();

    private int mCurrentTest = -1;
    int mBands = 4;
    AudioBandSpecs[] bandSpecsArray = new AudioBandSpecs[mBands];
    AudioBandSpecs[] baseBandSpecsArray = new AudioBandSpecs[mBands];

    int mMaxLevel;
    private class OnBtnClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.audio_frequency_mic_speakers_ready_btn:
                testSpeakersReady();
                break;
            case R.id.audio_frequency_mic_test1_btn:
                startTest1();
                break;
            case R.id.audio_frequency_mic_mic_ready_btn:
                testUSB();
                break;
            case R.id.audio_frequency_mic_test2_btn:
                startTest2();
                break;
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.audio_frequency_mic_activity);
        mContext = this;
        mSpeakerReadyText = (TextView) findViewById(R.id.audio_frequency_mic_speakers_ready_status);

        mSpeakersReady  = (Button)findViewById(R.id.audio_frequency_mic_speakers_ready_btn);
        mSpeakersReady.setOnClickListener(mBtnClickListener);
        mTest1Button = (Button)findViewById(R.id.audio_frequency_mic_test1_btn);
        mTest1Button.setOnClickListener(mBtnClickListener);
        mTest1Result = (TextView)findViewById(R.id.audio_frequency_mic_results1_text);
        mLayoutTest1 = (LinearLayout) findViewById(R.id.audio_frequency_mic_layout_test1);
        mLayoutTest2a = (LinearLayout) findViewById(R.id.audio_frequency_mic_layout_test2a);
        mLayoutTest2b = (LinearLayout) findViewById(R.id.audio_frequency_mic_layout_test2b);
        mUsbMicReady = (Button)findViewById(R.id.audio_frequency_mic_mic_ready_btn);
        mUsbMicReady.setOnClickListener(mBtnClickListener);

        mUsbStatusText = (TextView)findViewById(R.id.audio_frequency_mic_usb_status);
        mTest2Button = (Button)findViewById(R.id.audio_frequency_mic_test2_btn);
        mTest2Button.setOnClickListener(mBtnClickListener);
        mTest2Result = (TextView)findViewById(R.id.audio_frequency_mic_results_text);
        mProgressBar = (ProgressBar)findViewById(R.id.audio_frequency_mic_progress_bar);
        showWait(false);
        enableLayout(mLayoutTest1, false);
        enableLayout(mLayoutTest2a, false);
        enableLayout(mLayoutTest2b, false);

        mSPlayer = new SoundPlayerObject();
        mSPlayer.setSoundWithResId(getApplicationContext(), R.raw.stereo_mono_white_noise_48);
        mSPlayer.setBalance(0.5f);

        //Init FFT stuff
        mAudioShortArray2 = new short[mBlockSizeSamples*2];
        mData = new DspBufferDouble(mBlockSizeSamples);
        mC = new DspBufferComplex(mBlockSizeSamples);
        mFftServer = new DspFftServer(mBlockSizeSamples);

        int overlap = mBlockSizeSamples / 2;

        mWindow = new DspWindow(DspWindow.WINDOW_HANNING, mBlockSizeSamples, overlap);

        setPassFailButtonClickListeners();
        getPassButton().setEnabled(false);
        setInfoResources(R.string.audio_frequency_mic_test,
                R.string.audio_frequency_mic_info, -1);

        //Init bands for BuiltIn/Reference test
        bandSpecsArray[0] = new AudioBandSpecs(
                50, 500,        /* frequency start,stop */
                -20.0, -50,     /* start top,bottom value */
                4.0, -4.0       /* stop top,bottom value */);

        bandSpecsArray[1] = new AudioBandSpecs(
                500,4000,       /* frequency start,stop */
                4.0, -4.0,      /* start top,bottom value */
                4.0, -4.0        /* stop top,bottom value */);

        bandSpecsArray[2] = new AudioBandSpecs(
                4000, 12000,    /* frequency start,stop */
                4.0, -4.0,      /* start top,bottom value */
                5.0, -5.0       /* stop top,bottom value */);

        bandSpecsArray[3] = new AudioBandSpecs(
                12000, 20000,   /* frequency start,stop */
                5.0, -5.0,      /* start top,bottom value */
                5.0, -30.0      /* stop top,bottom value */);

        //Init base bands for silence
        baseBandSpecsArray[0] = new AudioBandSpecs(
                50, 500,        /* frequency start,stop */
                40.0, -50.0,     /* start top,bottom value */
                5.0, -50.0       /* stop top,bottom value */);

        baseBandSpecsArray[1] = new AudioBandSpecs(
                500,4000,       /* frequency start,stop */
                5.0, -50.0,      /* start top,bottom value */
                5.0, -50.0        /* stop top,bottom value */);

        baseBandSpecsArray[2] = new AudioBandSpecs(
                4000, 12000,    /* frequency start,stop */
                5.0, -50.0,      /* start top,bottom value */
                5.0, -50.0       /* stop top,bottom value */);

        baseBandSpecsArray[3] = new AudioBandSpecs(
                12000, 20000,   /* frequency start,stop */
                5.0, -50.0,      /* start top,bottom value */
                5.0, -50.0      /* stop top,bottom value */);

    }

    /**
     * enable test ui elements
     */
    private void enableLayout(LinearLayout layout, boolean enable) {
        for (int i = 0; i < layout.getChildCount(); i++) {
            View view = layout.getChildAt(i);
            view.setEnabled(enable);
        }
    }

    /**
     * show active progress bar
     */
    private void showWait(boolean show) {
        if (show) {
            mProgressBar.setVisibility(View.VISIBLE);
        } else {
            mProgressBar.setVisibility(View.INVISIBLE);
        }
    }

    private void setMaxLevel() {
        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        mMaxLevel = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        am.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(mMaxLevel), 0);
    }

    private void setMinLevel() {
        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        am.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
    }

    /**
     *  Start the loopback audio test
     */
    private void startTest1() {
        if (mTestThread != null && !mTestThread.isAlive()) {
            mTestThread = null; //kill it.
        }

        if (mTestThread == null) {
            Log.v(TAG,"Executing test Thread");
            mTestThread = new Thread(mTest1Runnable);
            //getPassButton().setEnabled(false);
            if (!mSPlayer.isAlive())
                mSPlayer.start();
            mTestThread.start();
        } else {
            Log.v(TAG,"test Thread already running.");
        }
    }

    Thread mTestThread;
    Runnable mTest1Runnable = new Runnable() {
        public void run() {
            Message msg = Message.obtain();
            msg.what = TEST_STARTED;
            mMessageHandler.sendMessage(msg);

            setMinLevel();
            sendMessage("Testing Background Environment");
            mCurrentTest = 0;
            mSPlayer.setBalance(0.5f);
            mFreqAverageBase.reset();
            play();

            setMaxLevel();
            sendMessage("Testing Built in Microphone");
            mCurrentTest = 1;
            mFreqAverageBuiltIn.reset();
            mSPlayer.setBalance(0.5f);
            play();

            mCurrentTest = -1;
            sendMessage("Testing Completed");

            Message msg2 = Message.obtain();
            msg2.what = TEST1_ENDED;
            mMessageHandler.sendMessage(msg2);
        }

        private void play() {
            startRecording();
            mSPlayer.play(true);

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                //restore interrupted status
                Thread.currentThread().interrupt();
            }

            mSPlayer.play(false);
            stopRecording();
        }

        private void sendMessage(String str) {
            Message msg = Message.obtain();
            msg.what = TEST1_MESSAGE;
            msg.obj = str;
            mMessageHandler.sendMessage(msg);
        }
    };

    /**
     *  Start the loopback audio test
     */
    private void startTest2() {
        if (mTestThread != null && !mTestThread.isAlive()) {
            mTestThread = null; //kill it.
        }

        if (mTestThread == null) {
            Log.v(TAG,"Executing test2 Thread");
            mTestThread = new Thread(mTest2Runnable);
            //getPassButton().setEnabled(false);
            if (!mSPlayer.isAlive())
                mSPlayer.start();
            mTestThread.start();
        } else {
            Log.v(TAG,"test Thread already running.");
        }
    }

    Runnable mTest2Runnable = new Runnable() {
        public void run() {
            Message msg = Message.obtain();
            msg.what = TEST_STARTED;
            mMessageHandler.sendMessage(msg);

            sendMessage("Testing Reference USB Microphone");
            mCurrentTest = 2;
            mFreqAverageReference.reset();
            mSPlayer.setBalance(0.5f);
            play();

            mCurrentTest = -1;
            sendMessage("Testing Completed");

            Message msg2 = Message.obtain();
            msg2.what = TEST_ENDED;
            mMessageHandler.sendMessage(msg2);
        }

        private void play() {
            startRecording();
            mSPlayer.play(true);

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                //restore interrupted status
                Thread.currentThread().interrupt();
            }

            mSPlayer.play(false);
            stopRecording();
        }

        private void sendMessage(String str) {
            Message msg = Message.obtain();
            msg.what = TEST_MESSAGE;
            msg.obj = str;
            mMessageHandler.sendMessage(msg);
        }
    };

    private Handler mMessageHandler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
            case TEST_STARTED:
                showWait(true);
                getPassButton().setEnabled(false);
                break;
            case TEST_ENDED:
                showWait(false);
                computeTest2Results();
                break;
            case TEST1_MESSAGE: {
                    String str = (String)msg.obj;
                    if (str != null) {
                        mTest1Result.setText(str);
                    }
                }
                break;
            case TEST1_ENDED:
                showWait(false);
                computeTest1Results();
                break;
            case TEST_MESSAGE: {
                    String str = (String)msg.obj;
                    if (str != null) {
                        mTest2Result.setText(str);
                    }
                }
                break;
            default:
                Log.e(TAG, String.format("Unknown message: %d", msg.what));
            }
        }
    };

    private class Results {
        private String mLabel;
        public double[] mValuesLog;
        int[] mPointsPerBand = new int[mBands];
        double[] mAverageEnergyPerBand = new double[mBands];
        int[] mInBoundPointsPerBand = new int[mBands];
        public boolean mIsBaseMeasurement = false;
        public Results(String label) {
            mLabel = label;
        }

        //append results
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(String.format("Channel %s\n", mLabel));
            sb.append("Level in Band 1 : " + (testLevel() ? "OK" :"FAILED") +
                    (mIsBaseMeasurement ? " (Base Meas.)" : "") + "\n");
            for (int b = 0; b < mBands; b++) {
                double percent = 0;
                if (mPointsPerBand[b] > 0) {
                    percent = 100.0 * (double) mInBoundPointsPerBand[b] / mPointsPerBand[b];
                }
                sb.append(String.format(
                        " Band %d: Av. Level: %.1f dB InBand: %d/%d (%.1f%%) %s\n",
                        b, mAverageEnergyPerBand[b],
                        mInBoundPointsPerBand[b],
                        mPointsPerBand[b],
                        percent,
                        (testInBand(b) ? "OK" : "FAILED")));
            }
            return sb.toString();
        }

        public boolean testLevel() {
            if (mIsBaseMeasurement && mAverageEnergyPerBand[1] <= MAX_ENERGY_BAND_1_BASE) {
                return true;
            } else if (mAverageEnergyPerBand[1] >= MIN_ENERGY_BAND_1) {
                return true;
            }
            return false;
        }

        public boolean testInBand(int b) {
            if (b >= 0 && b < mBands && mPointsPerBand[b] > 0) {
                if ((double) mInBoundPointsPerBand[b] / mPointsPerBand[b] >
                    MIN_FRACTION_POINTS_IN_BAND) {
                        return true;
                }
            }
            return false;
        }

        public boolean testAll() {
            if (!testLevel()) {
                return false;
            }
            for (int b = 0; b < mBands; b++) {
                if (!testInBand(b)) {
                    return false;
                }
            }
            return true;
        }
    }


    /**
     * compute test1 results
     */
    private void computeTest1Results() {

        Results resultsBase = new Results("Base");
        if (computeResultsForVector(mFreqAverageBase, resultsBase, true, baseBandSpecsArray)) {
            appendResultsToScreen(resultsBase.toString(), mTest1Result);
            recordTestResults(resultsBase);
        }

        Results resultsBuiltIn = new Results("BuiltIn");
        if (computeResultsForVector(mFreqAverageBuiltIn, resultsBuiltIn, false, bandSpecsArray)) {
            appendResultsToScreen(resultsBuiltIn.toString(), mTest1Result);
            recordTestResults(resultsBuiltIn);
        }

        //tell user to connect USB Microphone
        appendResultsToScreen("\n\n" +
                getResources().getText(R.string.audio_frequency_mic_connect_mic), mTest1Result);
        enableLayout(mLayoutTest2a, true);
    }

    /**
     * compute test results
     */
    private void computeTest2Results() {
        Results resultsReference = new Results("Reference");
        if (computeResultsForVector(mFreqAverageReference, resultsReference,
                false, bandSpecsArray)) {
            appendResultsToScreen(resultsReference.toString(),mTest2Result);
            recordTestResults(resultsReference);
            getPassButton().setEnabled(true);
        }
    }

    private boolean computeResultsForVector(VectorAverage freqAverage, Results results,
            boolean isBase, AudioBandSpecs[] bandSpecs) {

        results.mIsBaseMeasurement = isBase;
        int points = freqAverage.getSize();
        if (points > 0) {
            //compute vector in db
            double[] values = new double[points];
            freqAverage.getData(values, false);
            results.mValuesLog = new double[points];
            for (int i = 0; i < points; i++) {
                results.mValuesLog[i] = 20 * Math.log10(values[i]);
            }

            int currentBand = 0;
            for (int i = 0; i < points; i++) {
                double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples;
                if (freq > bandSpecs[currentBand].mFreqStop) {
                    currentBand++;
                    if (currentBand >= mBands)
                        break;
                }

                if (freq >= bandSpecs[currentBand].mFreqStart) {
                    results.mAverageEnergyPerBand[currentBand] += results.mValuesLog[i];
                    results.mPointsPerBand[currentBand]++;
                }
            }

            for (int b = 0; b < mBands; b++) {
                if (results.mPointsPerBand[b] > 0) {
                    results.mAverageEnergyPerBand[b] =
                            results.mAverageEnergyPerBand[b] / results.mPointsPerBand[b];
                }
            }

            //set offset relative to band 1 level
            for (int b = 0; b < mBands; b++) {
                bandSpecs[b].setOffset(results.mAverageEnergyPerBand[1]);
            }

            //test points in band.
            currentBand = 0;
            for (int i = 0; i < points; i++) {
                double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples;
                if (freq >  bandSpecs[currentBand].mFreqStop) {
                    currentBand++;
                    if (currentBand >= mBands)
                        break;
                }

                if (freq >= bandSpecs[currentBand].mFreqStart) {
                    double value = results.mValuesLog[i];
                    if (bandSpecs[currentBand].isInBounds(freq, value)) {
                        results.mInBoundPointsPerBand[currentBand]++;
                    }
                }
            }
            return true;
        } else {
            return false;
        }
    }

    //append results
    private void appendResultsToScreen(String str, TextView text) {
        String currentText = text.getText().toString();
        text.setText(currentText + "\n" + str);
    }

    /**
     * Store test results in log
     */
    private void recordTestResults(Results results) {
        String channelLabel = "channel_" + results.mLabel;

        for (int b = 0; b < mBands; b++) {
            String bandLabel = String.format(channelLabel + "_%d", b);
            getReportLog().addValue(
                    bandLabel + "_Level",
                    results.mAverageEnergyPerBand[b],
                    ResultType.HIGHER_BETTER,
                    ResultUnit.NONE);

            getReportLog().addValue(
                    bandLabel + "_pointsinbound",
                    results.mInBoundPointsPerBand[b],
                    ResultType.HIGHER_BETTER,
                    ResultUnit.COUNT);

            getReportLog().addValue(
                    bandLabel + "_pointstotal",
                    results.mPointsPerBand[b],
                    ResultType.NEUTRAL,
                    ResultUnit.COUNT);
        }

        getReportLog().addValues(channelLabel + "_magnitudeSpectrumLog",
                results.mValuesLog,
                ResultType.NEUTRAL,
                ResultUnit.NONE);

        Log.v(TAG, "Results Recorded");
    }

    private void startRecording() {
        synchronized (mRecordingLock) {
            mIsRecording = true;
        }

        boolean successful = initRecord();
        if (successful) {
            startRecordingForReal();
        } else {
            Log.v(TAG, "Recorder initialization error.");
            synchronized (mRecordingLock) {
                mIsRecording = false;
            }
        }
    }

    private void startRecordingForReal() {
        // start streaming
        if (mRecordThread == null) {
            mRecordThread = new Thread(AudioFrequencyMicActivity.this);
            mRecordThread.setName("FrequencyAnalyzerThread");
        }
        if (!mRecordThread.isAlive()) {
            mRecordThread.start();
        }

        mPipe.flush();

        long startTime = SystemClock.uptimeMillis();
        mRecorder.startRecording();
        if (mRecorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
            stopRecording();
            return;
        }
        Log.v(TAG, "Start time: " + (long) (SystemClock.uptimeMillis() - startTime) + " ms");
    }

    private void stopRecording() {
        synchronized (mRecordingLock) {
            stopRecordingForReal();
            mIsRecording = false;
        }
    }

    private void stopRecordingForReal() {

        // stop streaming
        Thread zeThread = mRecordThread;
        mRecordThread = null;
        if (zeThread != null) {
            zeThread.interrupt();
            try {
                zeThread.join();
            } catch(InterruptedException e) {
                //restore interrupted status of recording thread
                zeThread.interrupt();
            }
        }
         // release recording resources
        if (mRecorder != null) {
            mRecorder.stop();
            mRecorder.release();
            mRecorder = null;
        }
    }

    private boolean initRecord() {
        int minRecordBuffSizeInBytes = AudioRecord.getMinBufferSize(mSamplingRate,
                mChannelConfig, mAudioFormat);
        Log.v(TAG,"FrequencyAnalyzer: min buff size = " + minRecordBuffSizeInBytes + " bytes");
        if (minRecordBuffSizeInBytes <= 0) {
            return false;
        }

        mMinRecordBufferSizeInSamples = minRecordBuffSizeInBytes / 2;
        // allocate the byte array to read the audio data

        mAudioShortArray = new short[mMinRecordBufferSizeInSamples];

        Log.v(TAG, "Initiating record:");
        Log.v(TAG, "      using source " + mSelectedRecordSource);
        Log.v(TAG, "      at " + mSamplingRate + "Hz");

        try {
            mRecorder = new AudioRecord(mSelectedRecordSource, mSamplingRate,
                    mChannelConfig, mAudioFormat, 2 * minRecordBuffSizeInBytes);
        } catch (IllegalArgumentException e) {
            return false;
        }
        if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
            mRecorder.release();
            mRecorder = null;
            return false;
        }
        mRecorder.setRecordPositionUpdateListener(this);
        mRecorder.setPositionNotificationPeriod(mBlockSizeSamples / 2);
        return true;
    }

    // ---------------------------------------------------------
    // Implementation of AudioRecord.OnPeriodicNotificationListener
    // --------------------
    public void onPeriodicNotification(AudioRecord recorder) {
        int samplesAvailable = mPipe.availableToRead();
        int samplesNeeded = mBlockSizeSamples;
        if (samplesAvailable >= samplesNeeded) {
            mPipe.read(mAudioShortArray2, 0, samplesNeeded);

            //compute stuff.
            int clipcount = 0;
            double sum = 0;
            double maxabs = 0;
            int i;

            for (i = 0; i < samplesNeeded; i++) {
                double value = mAudioShortArray2[i] / MAX_VAL;
                double valueabs = Math.abs(value);

                if (valueabs > maxabs) {
                    maxabs = valueabs;
                }

                if (valueabs > CLIP_LEVEL) {
                    clipcount++;
                }

                sum += value * value;
                //fft stuff
                mData.mData[i] = value;
            }

            //for the current frame, compute FFT and send to the viewer.

            //apply window and pack as complex for now.
            DspBufferMath.mult(mData, mData, mWindow.mBuffer);
            DspBufferMath.set(mC, mData);
            mFftServer.fft(mC, 1);

            double[] halfMagnitude = new double[mBlockSizeSamples / 2];
            for (i = 0; i < mBlockSizeSamples / 2; i++) {
                halfMagnitude[i] = Math.sqrt(mC.mReal[i] * mC.mReal[i] + mC.mImag[i] * mC.mImag[i]);
            }

            mFreqAverageMain.setData(halfMagnitude, false); //average all of them!

            switch(mCurrentTest) {
                case 0:
                    mFreqAverageBase.setData(halfMagnitude, false);
                    break;
                case 1:
                    mFreqAverageBuiltIn.setData(halfMagnitude, false);
                    break;
                case 2:
                    mFreqAverageReference.setData(halfMagnitude, false);
                    break;
            }
        }
    }

    public void onMarkerReached(AudioRecord track) {
    }

    // ---------------------------------------------------------
    // Implementation of Runnable for the audio recording + playback
    // --------------------
    public void run() {
        Thread thisThread = Thread.currentThread();
        while (!thisThread.isInterrupted()) {
            // read from native recorder
            int nSamplesRead = mRecorder.read(mAudioShortArray, 0, mMinRecordBufferSizeInSamples);
            if (nSamplesRead > 0) {
                mPipe.write(mAudioShortArray, 0, nSamplesRead);
            }
        }
    }

    private void testSpeakersReady() {
        boolean isUsbConnected =
                UsbMicrophoneTester.getIsMicrophoneConnected(getApplicationContext());
        if (isUsbConnected) {
            mSpeakerReadyText.setText(" USB device detected, please remove it");
            enableLayout(mLayoutTest1, false);
            //fail
        } else {
            mSpeakerReadyText.setText(" No USB device detected. OK");
            enableLayout(mLayoutTest1, true);
        }
    }

    private void testUSB() {
        boolean isConnected = UsbMicrophoneTester.getIsMicrophoneConnected(getApplicationContext());
        mUsbDevicesInfo = UsbMicrophoneTester.getUSBDeviceListString(getApplicationContext());

        if (isConnected) {
            mUsbStatusText.setText(
                    getResources().getText(R.string.audio_frequency_mic_mic_ready_text));
            enableLayout(mLayoutTest2b, true);
        } else {
            mUsbStatusText.setText(
                    getResources().getText(R.string.audio_frequency_mic_mic_not_ready_text));
            enableLayout(mLayoutTest2b, false);
        }
    }

}
