19b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia/* 29b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * Copyright (C) 2015 The Android Open Source Project 39b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * 49b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * Licensed under the Apache License, Version 2.0 (the "License"); 59b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * you may not use this file except in compliance with the License. 69b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * You may obtain a copy of the License at 79b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * 89b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * http://www.apache.org/licenses/LICENSE-2.0 99b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * 109b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * Unless required by applicable law or agreed to in writing, software 119b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * distributed under the License is distributed on an "AS IS" BASIS, 129b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * See the License for the specific language governing permissions and 149b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * limitations under the License. 159b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia */ 169b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 179b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciapackage com.android.cts.verifier.audio; 189b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 199b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport com.android.cts.verifier.PassFailButtons; 209b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport com.android.cts.verifier.R; 219b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport com.android.cts.verifier.audio.wavelib.*; 229b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport com.android.compatibility.common.util.ReportLog; 239b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport com.android.compatibility.common.util.ResultType; 249b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport com.android.compatibility.common.util.ResultUnit; 259b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 26bf40d84ca078f71421bf1fff97dbf6265575df3bragoimport android.app.AlertDialog; 27e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garciaimport android.content.Context; 289b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.media.AudioDeviceCallback; 299b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.media.AudioDeviceInfo; 309b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.media.AudioFormat; 319b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.media.AudioManager; 329b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.media.AudioTrack; 339b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.media.AudioRecord; 349b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.media.MediaRecorder; 359b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.os.Bundle; 369b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.os.Handler; 379b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.os.Message; 389b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.os.SystemClock; 399b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.util.Log; 409b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.view.View; 419b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.view.View.OnClickListener; 429b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.widget.Button; 439b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.widget.TextView; 449b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.widget.SeekBar; 459b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.widget.LinearLayout; 469b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garciaimport android.widget.ProgressBar; 479b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 489b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia/** 499b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * Tests Audio Device roundtrip latency by using a loopback plug. 509b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia */ 51bf40d84ca078f71421bf1fff97dbf6265575df3bragopublic class AudioFrequencyLineActivity extends AudioFrequencyActivity implements Runnable, 529b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia AudioRecord.OnRecordPositionUpdateListener { 539b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private static final String TAG = "AudioFrequencyLineActivity"; 549b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 559b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia static final int TEST_STARTED = 900; 569b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia static final int TEST_ENDED = 901; 579b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia static final int TEST_MESSAGE = 902; 589b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia static final double MIN_ENERGY_BAND_1 = -20.0; 599b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia static final double MIN_FRACTION_POINTS_IN_BAND = 0.3; 609b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 619b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia OnBtnClickListener mBtnClickListener = new OnBtnClickListener(); 629b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Context mContext; 639b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 64a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie Button mHeadsetPortYes; 65a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie Button mHeadsetPortNo; 66a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie 679b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Button mLoopbackPlugReady; 689b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia LinearLayout mLinearLayout; 699b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Button mTestButton; 709b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia TextView mResultText; 719b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ProgressBar mProgressBar; 729b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //recording 739b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private boolean mIsRecording = false; 749b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private final Object mRecordingLock = new Object(); 759b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private AudioRecord mRecorder; 769b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private int mMinRecordBufferSizeInSamples = 0; 779b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private short[] mAudioShortArray; 789b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private short[] mAudioShortArray2; 799b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 809b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private final int mBlockSizeSamples = 1024; 819b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private final int mSamplingRate = 48000; 82bf40d84ca078f71421bf1fff97dbf6265575df3brago private final int mSelectedRecordSource = MediaRecorder.AudioSource.UNPROCESSED; 839b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private final int mChannelConfig = AudioFormat.CHANNEL_IN_MONO; 849b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 859b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private volatile Thread mRecordThread; 869b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private boolean mRecordThreadShutdown = false; 879b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 889b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia PipeShort mPipe = new PipeShort(65536); 899b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia SoundPlayerObject mSPlayer; 909b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 919b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private DspBufferComplex mC; 929b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private DspBufferDouble mData; 939b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 949b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private DspWindow mWindow; 959b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private DspFftServer mFftServer; 969b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private VectorAverage mFreqAverageMain = new VectorAverage(); 979b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 989b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private VectorAverage mFreqAverage0 = new VectorAverage(); 999b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private VectorAverage mFreqAverage1 = new VectorAverage(); 1009b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1019b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private int mCurrentTest = -1; 1029b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int mBands = 4; 1039b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia AudioBandSpecs[] bandSpecsArray = new AudioBandSpecs[mBands]; 1049b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1059b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private class OnBtnClickListener implements OnClickListener { 1069b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia @Override 1079b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public void onClick(View v) { 1089b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia switch (v.getId()) { 1099b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia case R.id.audio_frequency_line_plug_ready_btn: 1109b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.i(TAG, "audio loopback plug ready"); 1119b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //enable all the other views. 1129b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia enableLayout(true); 113bf40d84ca078f71421bf1fff97dbf6265575df3brago setMaxLevel(); 114bf40d84ca078f71421bf1fff97dbf6265575df3brago testMaxLevel(); 1159b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 1169b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia case R.id.audio_frequency_line_test_btn: 1179b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.i(TAG, "audio loopback test"); 1189b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia startAudioTest(); 1199b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 120a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie case R.id.audio_general_headset_yes: 121a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie Log.i(TAG, "User confirms Headset Port existence"); 122a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mLoopbackPlugReady.setEnabled(true); 123a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie recordHeasetPortFound(true); 124a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortYes.setEnabled(false); 125a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortNo.setEnabled(false); 126a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie break; 127a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie case R.id.audio_general_headset_no: 128a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie Log.i(TAG, "User denies Headset Port existence"); 129a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie recordHeasetPortFound(false); 130a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie getPassButton().setEnabled(true); 131a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortYes.setEnabled(false); 132a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortNo.setEnabled(false); 133a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie break; 1349b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 1359b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 1369b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 1379b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1389b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia @Override 1399b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia protected void onCreate(Bundle savedInstanceState) { 1409b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia super.onCreate(savedInstanceState); 1419b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia setContentView(R.layout.audio_frequency_line_activity); 1429b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1439b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mContext = this; 1449b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 145a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortYes = (Button)findViewById(R.id.audio_general_headset_yes); 146a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortYes.setOnClickListener(mBtnClickListener); 147a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortNo = (Button)findViewById(R.id.audio_general_headset_no); 148a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mHeadsetPortNo.setOnClickListener(mBtnClickListener); 149a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie 1509b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mLoopbackPlugReady = (Button)findViewById(R.id.audio_frequency_line_plug_ready_btn); 1519b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mLoopbackPlugReady.setOnClickListener(mBtnClickListener); 152a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie mLoopbackPlugReady.setEnabled(false); 1539b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mLinearLayout = (LinearLayout)findViewById(R.id.audio_frequency_line_layout); 1549b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mTestButton = (Button)findViewById(R.id.audio_frequency_line_test_btn); 1559b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mTestButton.setOnClickListener(mBtnClickListener); 1569b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mResultText = (TextView)findViewById(R.id.audio_frequency_line_results_text); 1579b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mProgressBar = (ProgressBar)findViewById(R.id.audio_frequency_line_progress_bar); 1589b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia showWait(false); 1599b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia enableLayout(false); //disabled all content 1609b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1619b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer = new SoundPlayerObject(); 1629b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer.setSoundWithResId(getApplicationContext(), R.raw.stereo_mono_white_noise_48); 1639b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer.setBalance(0.5f); 1649b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1659b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //Init FFT stuff 1669b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mAudioShortArray2 = new short[mBlockSizeSamples*2]; 1679b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mData = new DspBufferDouble(mBlockSizeSamples); 1689b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mC = new DspBufferComplex(mBlockSizeSamples); 1699b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mFftServer = new DspFftServer(mBlockSizeSamples); 1709b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1719b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int overlap = mBlockSizeSamples / 2; 1729b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1739b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mWindow = new DspWindow(DspWindow.WINDOW_HANNING, mBlockSizeSamples, overlap); 1749b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1759b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia setPassFailButtonClickListeners(); 1769b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia getPassButton().setEnabled(false); 1779b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia setInfoResources(R.string.audio_frequency_line_test, 1789b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia R.string.audio_frequency_line_info, -1); 1799b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1809b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //Init bands 1819b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandSpecsArray[0] = new AudioBandSpecs( 1829b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 50, 500, /* frequency start,stop */ 183b0d570c835aebd5d0eb8dadcb6679b57504e6851rago 4.0, -50, /* start top,bottom value */ 1849b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4.0, -4.0 /* stop top,bottom value */); 1859b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1869b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandSpecsArray[1] = new AudioBandSpecs( 1879b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 500,4000, /* frequency start,stop */ 1889b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4.0, -4.0, /* start top,bottom value */ 1899b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4.0, -4.0 /* stop top,bottom value */); 1909b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1919b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandSpecsArray[2] = new AudioBandSpecs( 1929b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4000, 12000, /* frequency start,stop */ 1939b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4.0, -4.0, /* start top,bottom value */ 1949b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5.0, -5.0 /* stop top,bottom value */); 1959b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 1969b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandSpecsArray[3] = new AudioBandSpecs( 1979b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 12000, 20000, /* frequency start,stop */ 1989b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5.0, -5.0, /* start top,bottom value */ 1999b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5.0, -30.0 /* stop top,bottom value */); 2009b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2019b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2029b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia /** 2039b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * enable test ui elements 2049b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia */ 2059b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void enableLayout(boolean enable) { 2069b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int i = 0; i < mLinearLayout.getChildCount(); i++) { 2079b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia View view = mLinearLayout.getChildAt(i); 2089b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia view.setEnabled(enable); 2099b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2109b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2119b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2129b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia /** 2139b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * show active progress bar 2149b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia */ 2159b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void showWait(boolean show) { 2169b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (show) { 2179b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mProgressBar.setVisibility(View.VISIBLE); 2189b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } else { 2199b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mProgressBar.setVisibility(View.INVISIBLE); 2209b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2219b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2229b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2239b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia /** 2249b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * Start the loopback audio test 2259b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia */ 2269b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void startAudioTest() { 2279b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mTestThread != null && !mTestThread.isAlive()) { 2289b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mTestThread = null; //kill it. 2299b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2309b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2319b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mTestThread == null) { 2329b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG,"Executing test Thread"); 2339b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mTestThread = new Thread(mPlayRunnable); 2349b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia getPassButton().setEnabled(false); 2359b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (!mSPlayer.isAlive()) 2369b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer.start(); 2379b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mTestThread.start(); 2389b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } else { 2399b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG,"test Thread already running."); 2409b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2419b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2429b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2439b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Thread mTestThread; 2449b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Runnable mPlayRunnable = new Runnable() { 2459b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public void run() { 2469b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Message msg = Message.obtain(); 2479b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia msg.what = TEST_STARTED; 2489b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mMessageHandler.sendMessage(msg); 2499b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2509b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia sendMessage("Testing Left Capture"); 2519b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mCurrentTest = 0; 2529b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mFreqAverage0.reset(); 2539b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer.setBalance(0.0f); 2549b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia play(); 2559b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2569b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia sendMessage("Testing Right Capture"); 2579b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mCurrentTest = 1; 2589b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mFreqAverage1.reset(); 2599b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer.setBalance(1.0f); 2609b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia play(); 2619b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2629b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mCurrentTest = -1; 2639b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia sendMessage("Testing Completed"); 2649b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2659b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Message msg2 = Message.obtain(); 2669b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia msg2.what = TEST_ENDED; 2679b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mMessageHandler.sendMessage(msg2); 2689b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2699b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2709b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void play() { 2719b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia startRecording(); 2729b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer.play(true); 2739b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2749b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia try { 2759b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Thread.sleep(2000); 2769b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } catch (InterruptedException e) { 2779b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia e.printStackTrace(); 2789b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2799b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2809b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mSPlayer.play(false); 2819b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia stopRecording(); 2829b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2839b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2849b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void sendMessage(String str) { 2859b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Message msg = Message.obtain(); 2869b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia msg.what = TEST_MESSAGE; 2879b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia msg.obj = str; 2889b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mMessageHandler.sendMessage(msg); 2899b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 2909b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia }; 2919b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 2929b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private Handler mMessageHandler = new Handler() { 2939b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public void handleMessage(Message msg) { 2949b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia super.handleMessage(msg); 2959b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia switch (msg.what) { 2969b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia case TEST_STARTED: 2979b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia showWait(true); 2989b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia getPassButton().setEnabled(false); 2999b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 3009b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia case TEST_ENDED: 3019b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia showWait(false); 3029b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia computeResults(); 3039b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 3049b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia case TEST_MESSAGE: 3059b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia String str = (String)msg.obj; 3069b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (str != null) { 3079b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mResultText.setText(str); 3089b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3099b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 3109b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia default: 3119b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.e(TAG, String.format("Unknown message: %d", msg.what)); 3129b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3139b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3149b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia }; 3159b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3169b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private class Results { 3179b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private String mLabel; 3189b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public double[] mValuesLog; 3199b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int[] mPointsPerBand = new int[mBands]; 3209b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double[] mAverageEnergyPerBand = new double[mBands]; 3219b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int[] mInBoundPointsPerBand = new int[mBands]; 3229b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public Results(String label) { 3239b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mLabel = label; 3249b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3259b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3269b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //append results 3279b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public String toString() { 3289b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia StringBuilder sb = new StringBuilder(); 3299b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia sb.append(String.format("Channel %s\n", mLabel)); 330b0d570c835aebd5d0eb8dadcb6679b57504e6851rago sb.append("Level in Band 1 : " + (testLevel() ? "OK" :"Not Optimal") +"\n"); 3319b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int b = 0; b < mBands; b++) { 3329b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double percent = 0; 3339b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mPointsPerBand[b] > 0) { 3349b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia percent = 100.0 * (double)mInBoundPointsPerBand[b] / mPointsPerBand[b]; 3359b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3369b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia sb.append(String.format( 3379b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia " Band %d: Av. Level: %.1f dB InBand: %d/%d (%.1f%%) %s\n", 3389b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia b, mAverageEnergyPerBand[b], 3399b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mInBoundPointsPerBand[b], 3409b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mPointsPerBand[b], 3419b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia percent, 342b0d570c835aebd5d0eb8dadcb6679b57504e6851rago (testInBand(b) ? "OK" : "Not Optimal"))); 3439b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3449b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return sb.toString(); 3459b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3469b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3479b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public boolean testLevel() { 3489b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mAverageEnergyPerBand[1] >= MIN_ENERGY_BAND_1) { 3499b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return true; 3509b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3519b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return false; 3529b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3539b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3549b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public boolean testInBand(int b) { 3559b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (b >= 0 && b < mBands && mPointsPerBand[b] > 0) { 3569b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if ((double)mInBoundPointsPerBand[b] / mPointsPerBand[b] > 3579b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia MIN_FRACTION_POINTS_IN_BAND) 3589b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return true; 3599b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3609b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return false; 3619b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3629b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3639b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public boolean testAll() { 3649b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (!testLevel()) { 3659b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return false; 3669b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3679b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int b = 0; b < mBands; b++) { 3689b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (!testInBand(b)) { 3699b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return false; 3709b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3719b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3729b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return true; 3739b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3749b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3759b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3769b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia /** 3779b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * compute test results 3789b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia */ 3799b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void computeResults() { 3809b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Results resultsLeft = new Results("Left"); 3819b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia computeResultsForVector(mFreqAverage0, resultsLeft); 3829b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Results resultsRight = new Results("Right"); 3839b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia computeResultsForVector(mFreqAverage1, resultsRight); 3849b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (resultsLeft.testAll() && resultsRight.testAll()) { 385e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia String strSuccess = getResources().getString(R.string.audio_general_test_passed); 386e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia appendResultsToScreen(strSuccess); 387e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia } else { 388e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia String strFailed = getResources().getString(R.string.audio_general_test_failed); 389e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia appendResultsToScreen(strFailed + "\n"); 390e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia String strWarning = getResources().getString(R.string.audio_general_deficiency_found); 391e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia appendResultsToScreen(strWarning); 3929b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 393e8a13b1bdeb1f6a610720d8c0393dd5c3e982055Ricardo Garcia getPassButton().setEnabled(true); //Everybody passes! (for now...) 3949b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 3959b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3969b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void computeResultsForVector(VectorAverage freqAverage,Results results) { 3979b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 3989b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int points = freqAverage.getSize(); 3999b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (points > 0) { 4009b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //compute vector in db 4019b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double[] values = new double[points]; 4029b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia freqAverage.getData(values, false); 4039b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mValuesLog = new double[points]; 4049b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int i = 0; i < points; i++) { 4059b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mValuesLog[i] = 20 * Math.log10(values[i]); 4069b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4079b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4089b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int currentBand = 0; 4099b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int i = 0; i < points; i++) { 4109b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples; 4119b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (freq > bandSpecsArray[currentBand].mFreqStop) { 4129b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia currentBand++; 4139b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (currentBand >= mBands) 4149b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 4159b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4169b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4179b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (freq >= bandSpecsArray[currentBand].mFreqStart) { 4189b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mAverageEnergyPerBand[currentBand] += results.mValuesLog[i]; 4199b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mPointsPerBand[currentBand]++; 4209b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4219b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4229b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4239b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int b = 0; b < mBands; b++) { 4249b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (results.mPointsPerBand[b] > 0) { 4259b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mAverageEnergyPerBand[b] = 4269b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mAverageEnergyPerBand[b] / results.mPointsPerBand[b]; 4279b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4289b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4299b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4309b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //set offset relative to band 1 level 4319b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int b = 0; b < mBands; b++) { 4329b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandSpecsArray[b].setOffset(results.mAverageEnergyPerBand[1]); 4339b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4349b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4359b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //test points in band. 4369b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia currentBand = 0; 4379b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int i = 0; i < points; i++) { 4389b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples; 4399b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (freq > bandSpecsArray[currentBand].mFreqStop) { 4409b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia currentBand++; 4419b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (currentBand >= mBands) 4429b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 4439b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4449b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4459b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (freq >= bandSpecsArray[currentBand].mFreqStart) { 4469b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double value = results.mValuesLog[i]; 4479b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (bandSpecsArray[currentBand].isInBounds(freq, value)) { 4489b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mInBoundPointsPerBand[currentBand]++; 4499b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4509b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4519b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4529b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4539b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia appendResultsToScreen(results.toString()); 4549b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //store results 4559b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia recordTestResults(results); 4569b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } else { 4579b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia appendResultsToScreen("Failed testing channel " + results.mLabel); 4589b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4599b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4609b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4619b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //append results 4629b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void appendResultsToScreen(String str) { 4639b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia String currentText = mResultText.getText().toString(); 4649b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mResultText.setText(currentText + "\n" + str); 4659b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4669b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4679b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia /** 4689b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia * Store test results in log 4699b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia */ 4709b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void recordTestResults(Results results) { 4719b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia String channelLabel = "channel_" + results.mLabel; 4729b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4739b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (int b = 0; b < mBands; b++) { 4749b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia String bandLabel = String.format(channelLabel + "_%d", b); 4759b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia getReportLog().addValue( 4769b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandLabel + "_Level", 4779b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mAverageEnergyPerBand[b], 4789b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultType.HIGHER_BETTER, 4799b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultUnit.NONE); 4809b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4819b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia getReportLog().addValue( 4829b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandLabel + "_pointsinbound", 4839b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mInBoundPointsPerBand[b], 4849b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultType.HIGHER_BETTER, 4859b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultUnit.COUNT); 4869b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4879b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia getReportLog().addValue( 4889b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia bandLabel + "_pointstotal", 4899b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mPointsPerBand[b], 4909b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultType.NEUTRAL, 4919b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultUnit.COUNT); 4929b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 4939b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4949b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia getReportLog().addValues(channelLabel + "_magnitudeSpectrumLog", 4959b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia results.mValuesLog, 4969b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultType.NEUTRAL, 4979b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia ResultUnit.NONE); 4989b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 4999b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG, "Results Recorded"); 5009b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5019b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 502a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie private void recordHeasetPortFound(boolean found) { 503a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie getReportLog().addValue( 504a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie "User Reported Headset Port", 505a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie found ? 1.0 : 0, 506a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie ResultType.NEUTRAL, 507a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie ResultUnit.NONE); 508a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie } 509a41d49723a200eec6af9c9504a961cb2df306295Daniel Xie 5109b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void startRecording() { 5119b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia synchronized (mRecordingLock) { 5129b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mIsRecording = true; 5139b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5149b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5159b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia boolean successful = initRecord(); 5169b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (successful) { 5179b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia startRecordingForReal(); 5189b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } else { 5199b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG, "Recorder initialization error."); 5209b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia synchronized (mRecordingLock) { 5219b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mIsRecording = false; 5229b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5239b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5249b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5259b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5269b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void startRecordingForReal() { 5279b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // start streaming 5289b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mRecordThread == null) { 5299b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecordThread = new Thread(AudioFrequencyLineActivity.this); 5309b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecordThread.setName("FrequencyAnalyzerThread"); 5319b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecordThreadShutdown = false; 5329b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5339b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (!mRecordThread.isAlive()) { 5349b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecordThread.start(); 5359b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5369b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5379b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mPipe.flush(); 5389b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5399b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia long startTime = SystemClock.uptimeMillis(); 5409b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder.startRecording(); 5419b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mRecorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) { 5429b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia stopRecording(); 5439b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return; 5449b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5459b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG, "Start time: " + (long) (SystemClock.uptimeMillis() - startTime) + " ms"); 5469b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5479b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5489b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void stopRecording() { 5499b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia synchronized (mRecordingLock) { 5509b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia stopRecordingForReal(); 5519b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mIsRecording = false; 5529b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5539b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5549b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5559b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private void stopRecordingForReal() { 5569b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5579b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // stop streaming 5589b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Thread zeThread = mRecordThread; 5599b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecordThread = null; 5609b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecordThreadShutdown = true; 5619b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (zeThread != null) { 5629b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia zeThread.interrupt(); 5639b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia try { 5649b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia zeThread.join(); 5659b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } catch(InterruptedException e) { 5669b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG,"Error shutting down recording thread " + e); 5679b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //we don't really care about this error, just logging it. 5689b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5699b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5709b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // release recording resources 5719b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mRecorder != null) { 5729b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder.stop(); 5739b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder.release(); 5749b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder = null; 5759b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5769b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5779b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5789b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia private boolean initRecord() { 5799b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int minRecordBuffSizeInBytes = AudioRecord.getMinBufferSize(mSamplingRate, 5809b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mChannelConfig, mAudioFormat); 5819b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG,"FrequencyAnalyzer: min buff size = " + minRecordBuffSizeInBytes + " bytes"); 5829b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (minRecordBuffSizeInBytes <= 0) { 5839b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return false; 5849b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 5859b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5869b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mMinRecordBufferSizeInSamples = minRecordBuffSizeInBytes / 2; 5879b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // allocate the byte array to read the audio data 5889b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5899b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mAudioShortArray = new short[mMinRecordBufferSizeInSamples]; 5909b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5919b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG, "Initiating record:"); 5929b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG, " using source " + mSelectedRecordSource); 5939b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Log.v(TAG, " at " + mSamplingRate + "Hz"); 5949b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 5959b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia try { 5969b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder = new AudioRecord(mSelectedRecordSource, mSamplingRate, 5979b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mChannelConfig, mAudioFormat, 2 * minRecordBuffSizeInBytes); 5989b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } catch (IllegalArgumentException e) { 59986df641ad36b8a57cc2c49db7d7df2606273261erago Log.v(TAG, "Error: " + e.toString()); 6009b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return false; 6019b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6029b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) { 6039b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder.release(); 6049b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder = null; 60586df641ad36b8a57cc2c49db7d7df2606273261erago Log.v(TAG, "Error: mRecorder not initialized"); 6069b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return false; 6079b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6089b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder.setRecordPositionUpdateListener(this); 6099b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mRecorder.setPositionNotificationPeriod(mBlockSizeSamples / 2); 6109b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia return true; 6119b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6129b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6139b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // --------------------------------------------------------- 6149b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // Implementation of AudioRecord.OnPeriodicNotificationListener 6159b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // -------------------- 6169b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public void onPeriodicNotification(AudioRecord recorder) { 6179b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int samplesAvailable = mPipe.availableToRead(); 6189b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int samplesNeeded = mBlockSizeSamples; 6199b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (samplesAvailable >= samplesNeeded) { 6209b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mPipe.read(mAudioShortArray2, 0, samplesNeeded); 6219b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6229b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //compute stuff. 6239b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double maxval = Math.pow(2, 15); 6249b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int clipcount = 0; 6259b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double cliplevel = (maxval-10) / maxval; 6269b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double sum = 0; 6279b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double maxabs = 0; 6289b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int i; 6299b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int index = 0; 6309b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6319b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (i = 0; i < samplesNeeded; i++) { 6329b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double value = mAudioShortArray2[i] / maxval; 6339b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double valueabs = Math.abs(value); 6349b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6359b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (valueabs > maxabs) { 6369b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia maxabs = valueabs; 6379b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6389b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6399b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (valueabs > cliplevel) { 6409b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia clipcount++; 6419b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6429b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6439b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia sum += value * value; 6449b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //fft stuff 6459b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (index < mBlockSizeSamples) { 6469b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mData.mData[index] = value; 6479b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6489b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia index++; 6499b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6509b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6519b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //for the current frame, compute FFT and send to the viewer. 6529b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6539b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia //apply window and pack as complex for now. 6549b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia DspBufferMath.mult(mData, mData, mWindow.mBuffer); 6559b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia DspBufferMath.set(mC, mData); 6569b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mFftServer.fft(mC, 1); 6579b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6589b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia double[] halfMagnitude = new double[mBlockSizeSamples / 2]; 6599b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia for (i = 0; i < mBlockSizeSamples / 2; i++) { 6609b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia halfMagnitude[i] = Math.sqrt(mC.mReal[i] * mC.mReal[i] + mC.mImag[i] * mC.mImag[i]); 6619b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6629b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6639b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mFreqAverageMain.setData(halfMagnitude, false); //average all of them! 6649b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6659b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia switch(mCurrentTest) { 6669b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia case 0: 6679b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mFreqAverage0.setData(halfMagnitude, false); 6689b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 6699b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia case 1: 6709b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mFreqAverage1.setData(halfMagnitude, false); 6719b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia break; 6729b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6739b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6749b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6759b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6769b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public void onMarkerReached(AudioRecord track) { 6779b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6789b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6799b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // --------------------------------------------------------- 6809b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // Implementation of Runnable for the audio recording + playback 6819b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // -------------------- 6829b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia public void run() { 6839b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia int nSamplesRead = 0; 6849b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia 6859b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia Thread thisThread = Thread.currentThread(); 6869b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia while (mRecordThread == thisThread && !mRecordThreadShutdown) { 6879b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia // read from native recorder 6889b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia nSamplesRead = mRecorder.read(mAudioShortArray, 0, mMinRecordBufferSizeInSamples); 6899b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia if (nSamplesRead > 0) { 6909b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia mPipe.write(mAudioShortArray, 0, nSamplesRead); 6919b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6929b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6939b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia } 6949b2e1681f819520fa41cf8d8c54df893f59109f5Ricardo Garcia} 695