1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.verifier.audio; 18 19 import com.android.cts.verifier.PassFailButtons; 20 import com.android.cts.verifier.R; 21 import com.android.cts.verifier.audio.wavelib.*; 22 import com.android.compatibility.common.util.ReportLog; 23 import com.android.compatibility.common.util.ResultType; 24 import com.android.compatibility.common.util.ResultUnit; 25 import android.content.Context; 26 import android.content.BroadcastReceiver; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 30 import android.media.AudioDeviceCallback; 31 import android.media.AudioDeviceInfo; 32 import android.media.AudioFormat; 33 import android.media.AudioManager; 34 import android.media.AudioTrack; 35 import android.media.AudioRecord; 36 import android.media.MediaRecorder; 37 38 import android.os.Bundle; 39 import android.os.Handler; 40 import android.os.Message; 41 import android.os.SystemClock; 42 43 import android.util.Log; 44 45 import android.view.View; 46 import android.view.View.OnClickListener; 47 48 import android.widget.Button; 49 import android.widget.TextView; 50 import android.widget.SeekBar; 51 import android.widget.LinearLayout; 52 import android.widget.ProgressBar; 53 54 /** 55 * Tests Audio Device roundtrip latency by using a loopback plug. 56 */ 57 public class AudioFrequencySpeakerActivity extends AudioFrequencyActivity implements Runnable, 58 AudioRecord.OnRecordPositionUpdateListener { 59 private static final String TAG = "AudioFrequencySpeakerActivity"; 60 61 static final int TEST_STARTED = 900; 62 static final int TEST_ENDED = 901; 63 static final int TEST_MESSAGE = 902; 64 static final double MIN_ENERGY_BAND_1 = -50.0; //dB Full Scale 65 static final double MAX_ENERGY_BAND_1_BASE = -60.0; //dB Full Scale 66 static final double MIN_FRACTION_POINTS_IN_BAND = 0.3; 67 68 final OnBtnClickListener mBtnClickListener = new OnBtnClickListener(); 69 Context mContext; 70 71 Button mLoopbackPlugReady; //user signal to have connected USB Microphone 72 Button mTestButton; //user to start test 73 String mUsbDevicesInfo; //usb device info for report 74 LinearLayout mLinearLayout; 75 TextView mResultText; 76 TextView mUsbStatusText; 77 ProgressBar mProgressBar; 78 79 private boolean mIsRecording = false; 80 private final Object mRecordingLock = new Object(); 81 private AudioRecord mRecorder; 82 private int mMinRecordBufferSizeInSamples = 0; 83 private short[] mAudioShortArray; 84 private short[] mAudioShortArray2; 85 86 private final int mBlockSizeSamples = 1024; 87 private final int mSamplingRate = 48000; 88 private final int mSelectedRecordSource = MediaRecorder.AudioSource.VOICE_RECOGNITION; 89 private final int mChannelConfig = AudioFormat.CHANNEL_IN_MONO; 90 private final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 91 private Thread mRecordThread; 92 private boolean mRecordThreadShutdown = false; 93 94 PipeShort mPipe = new PipeShort(65536); 95 SoundPlayerObject mSPlayer; 96 97 private DspBufferComplex mC; 98 private DspBufferDouble mData; 99 100 private DspWindow mWindow; 101 private DspFftServer mFftServer; 102 private VectorAverage mFreqAverageMain = new VectorAverage(); 103 104 private VectorAverage mFreqAverageBase = new VectorAverage(); 105 private VectorAverage mFreqAverageLeft = new VectorAverage(); 106 private VectorAverage mFreqAverageRight = new VectorAverage(); 107 108 private int mCurrentTest = -1; 109 int mBands = 4; 110 AudioBandSpecs[] bandSpecsArray = new AudioBandSpecs[mBands]; 111 AudioBandSpecs[] baseBandSpecsArray = new AudioBandSpecs[mBands]; 112 113 private class OnBtnClickListener implements OnClickListener { 114 @Override onClick(View v)115 public void onClick(View v) { 116 switch (v.getId()) { 117 case R.id.audio_frequency_speaker_mic_ready_btn: 118 testUSB(); 119 setMaxLevel(); 120 testMaxLevel(); 121 break; 122 case R.id.audio_frequency_speaker_test_btn: 123 startAudioTest(); 124 break; 125 } 126 } 127 } 128 129 @Override onCreate(Bundle savedInstanceState)130 protected void onCreate(Bundle savedInstanceState) { 131 super.onCreate(savedInstanceState); 132 setContentView(R.layout.audio_frequency_speaker_activity); 133 134 mContext = this; 135 136 mLoopbackPlugReady = (Button)findViewById(R.id.audio_frequency_speaker_mic_ready_btn); 137 mLoopbackPlugReady.setOnClickListener(mBtnClickListener); 138 mLinearLayout = (LinearLayout)findViewById(R.id.audio_frequency_speaker_layout); 139 mUsbStatusText = (TextView)findViewById(R.id.audio_frequency_speaker_usb_status); 140 mTestButton = (Button)findViewById(R.id.audio_frequency_speaker_test_btn); 141 mTestButton.setOnClickListener(mBtnClickListener); 142 mResultText = (TextView)findViewById(R.id.audio_frequency_speaker_results_text); 143 mProgressBar = (ProgressBar)findViewById(R.id.audio_frequency_speaker_progress_bar); 144 showWait(false); 145 enableLayout(false); //disabled all content 146 147 mSPlayer = new SoundPlayerObject(); 148 mSPlayer.setSoundWithResId(getApplicationContext(), R.raw.stereo_mono_white_noise_48); 149 mSPlayer.setBalance(0.5f); 150 151 //Init FFT stuff 152 mAudioShortArray2 = new short[mBlockSizeSamples*2]; 153 mData = new DspBufferDouble(mBlockSizeSamples); 154 mC = new DspBufferComplex(mBlockSizeSamples); 155 mFftServer = new DspFftServer(mBlockSizeSamples); 156 157 int overlap = mBlockSizeSamples / 2; 158 159 mWindow = new DspWindow(DspWindow.WINDOW_HANNING, mBlockSizeSamples, overlap); 160 161 setPassFailButtonClickListeners(); 162 getPassButton().setEnabled(false); 163 setInfoResources(R.string.audio_frequency_speaker_test, 164 R.string.audio_frequency_speaker_info, -1); 165 166 //Init bands for Left/Right test 167 bandSpecsArray[0] = new AudioBandSpecs( 168 50, 500, /* frequency start,stop */ 169 4.0, -50, /* start top,bottom value */ 170 4.0, -4.0 /* stop top,bottom value */); 171 172 bandSpecsArray[1] = new AudioBandSpecs( 173 500,4000, /* frequency start,stop */ 174 4.0, -4.0, /* start top,bottom value */ 175 4.0, -4.0 /* stop top,bottom value */); 176 177 bandSpecsArray[2] = new AudioBandSpecs( 178 4000, 12000, /* frequency start,stop */ 179 4.0, -4.0, /* start top,bottom value */ 180 5.0, -5.0 /* stop top,bottom value */); 181 182 bandSpecsArray[3] = new AudioBandSpecs( 183 12000, 20000, /* frequency start,stop */ 184 5.0, -5.0, /* start top,bottom value */ 185 5.0, -30.0 /* stop top,bottom value */); 186 187 //Init base bands for silence 188 baseBandSpecsArray[0] = new AudioBandSpecs( 189 50, 500, /* frequency start,stop */ 190 40.0, -50.0, /* start top,bottom value */ 191 5.0, -50.0 /* stop top,bottom value */); 192 193 baseBandSpecsArray[1] = new AudioBandSpecs( 194 500,4000, /* frequency start,stop */ 195 5.0, -50.0, /* start top,bottom value */ 196 5.0, -50.0 /* stop top,bottom value */); 197 198 baseBandSpecsArray[2] = new AudioBandSpecs( 199 4000, 12000, /* frequency start,stop */ 200 5.0, -50.0, /* start top,bottom value */ 201 5.0, -50.0 /* stop top,bottom value */); 202 203 baseBandSpecsArray[3] = new AudioBandSpecs( 204 12000, 20000, /* frequency start,stop */ 205 5.0, -50.0, /* start top,bottom value */ 206 5.0, -50.0 /* stop top,bottom value */); 207 208 } 209 210 /** 211 * enable test ui elements 212 */ enableLayout(boolean enable)213 private void enableLayout(boolean enable) { 214 for (int i = 0; i < mLinearLayout.getChildCount(); i++) { 215 View view = mLinearLayout.getChildAt(i); 216 view.setEnabled(enable); 217 } 218 } 219 220 /** 221 * show active progress bar 222 */ showWait(boolean show)223 private void showWait(boolean show) { 224 if (show) { 225 mProgressBar.setVisibility(View.VISIBLE); 226 } else { 227 mProgressBar.setVisibility(View.INVISIBLE); 228 } 229 } 230 231 /** 232 * Start the loopback audio test 233 */ startAudioTest()234 private void startAudioTest() { 235 if (mTestThread != null && !mTestThread.isAlive()) { 236 mTestThread = null; //kill it. 237 } 238 239 if (mTestThread == null) { 240 Log.v(TAG,"Executing test Thread"); 241 mTestThread = new Thread(mPlayRunnable); 242 getPassButton().setEnabled(false); 243 if (!mSPlayer.isAlive()) 244 mSPlayer.start(); 245 mTestThread.start(); 246 } else { 247 Log.v(TAG,"test Thread already running."); 248 } 249 } 250 251 Thread mTestThread; 252 Runnable mPlayRunnable = new Runnable() { 253 public void run() { 254 Message msg = Message.obtain(); 255 msg.what = TEST_STARTED; 256 mMessageHandler.sendMessage(msg); 257 258 setMinLevel(); 259 sendMessage("Testing Background Environment"); 260 mCurrentTest = 0; 261 mSPlayer.setBalance(0.5f); 262 mFreqAverageBase.reset(); 263 play(); 264 265 setMaxLevel(); 266 sendMessage("Testing Left Capture"); 267 mCurrentTest = 1; 268 mFreqAverageLeft.reset(); 269 mSPlayer.setBalance(0.0f); 270 play(); 271 272 sendMessage("Testing Right Capture"); 273 mCurrentTest = 2; 274 mFreqAverageRight.reset(); 275 mSPlayer.setBalance(1.0f); 276 play(); 277 278 mCurrentTest = -1; 279 sendMessage("Testing Completed"); 280 281 Message msg2 = Message.obtain(); 282 msg2.what = TEST_ENDED; 283 mMessageHandler.sendMessage(msg2); 284 } 285 286 private void play() { 287 startRecording(); 288 mSPlayer.play(true); 289 290 try { 291 Thread.sleep(2000); 292 } catch (InterruptedException e) { 293 e.printStackTrace(); 294 } 295 296 mSPlayer.play(false); 297 stopRecording(); 298 } 299 300 private void sendMessage(String str) { 301 Message msg = Message.obtain(); 302 msg.what = TEST_MESSAGE; 303 msg.obj = str; 304 mMessageHandler.sendMessage(msg); 305 } 306 }; 307 308 private Handler mMessageHandler = new Handler() { 309 public void handleMessage(Message msg) { 310 super.handleMessage(msg); 311 switch (msg.what) { 312 case TEST_STARTED: 313 showWait(true); 314 getPassButton().setEnabled(false); 315 break; 316 case TEST_ENDED: 317 showWait(false); 318 computeResults(); 319 break; 320 case TEST_MESSAGE: 321 String str = (String)msg.obj; 322 if (str != null) { 323 mResultText.setText(str); 324 } 325 break; 326 default: 327 Log.e(TAG, String.format("Unknown message: %d", msg.what)); 328 } 329 } 330 }; 331 332 private class Results { 333 private String mLabel; 334 public double[] mValuesLog; 335 int[] mPointsPerBand = new int[mBands]; 336 double[] mAverageEnergyPerBand = new double[mBands]; 337 int[] mInBoundPointsPerBand = new int[mBands]; 338 public boolean mIsBaseMeasurement = false; Results(String label)339 public Results(String label) { 340 mLabel = label; 341 } 342 343 //append results toString()344 public String toString() { 345 StringBuilder sb = new StringBuilder(); 346 sb.append(String.format("Channel %s\n", mLabel)); 347 sb.append("Level in Band 1 : " + (testLevel() ? "OK" :"Not Optimal") + 348 (mIsBaseMeasurement ? " (Base Meas.)" : "") + "\n"); 349 for (int b = 0; b < mBands; b++) { 350 double percent = 0; 351 if (mPointsPerBand[b] > 0) { 352 percent = 100.0 * (double)mInBoundPointsPerBand[b] / mPointsPerBand[b]; 353 } 354 sb.append(String.format( 355 " Band %d: Av. Level: %.1f dB InBand: %d/%d (%.1f%%) %s\n", 356 b, mAverageEnergyPerBand[b], 357 mInBoundPointsPerBand[b], 358 mPointsPerBand[b], 359 percent, 360 (testInBand(b) ? "OK" : "Not Optimal"))); 361 } 362 return sb.toString(); 363 } 364 testLevel()365 public boolean testLevel() { 366 if (mIsBaseMeasurement && mAverageEnergyPerBand[1] <= MAX_ENERGY_BAND_1_BASE) { 367 return true; 368 } else if (mAverageEnergyPerBand[1] >= MIN_ENERGY_BAND_1) { 369 return true; 370 } 371 return false; 372 } 373 testInBand(int b)374 public boolean testInBand(int b) { 375 if (b >= 0 && b < mBands && mPointsPerBand[b] > 0) { 376 if ((double)mInBoundPointsPerBand[b] / mPointsPerBand[b] > 377 MIN_FRACTION_POINTS_IN_BAND) 378 return true; 379 } 380 return false; 381 } 382 testAll()383 public boolean testAll() { 384 if (!testLevel()) { 385 return false; 386 } 387 for (int b = 0; b < mBands; b++) { 388 if (!testInBand(b)) { 389 return false; 390 } 391 } 392 return true; 393 } 394 } 395 396 /** 397 * compute test results 398 */ computeResults()399 private void computeResults() { 400 401 Results resultsBase = new Results("Base"); 402 computeResultsForVector(mFreqAverageBase, resultsBase, true, baseBandSpecsArray); 403 Results resultsLeft = new Results("Left"); 404 computeResultsForVector(mFreqAverageLeft, resultsLeft, false, bandSpecsArray); 405 Results resultsRight = new Results("Right"); 406 computeResultsForVector(mFreqAverageRight, resultsRight, false, bandSpecsArray); 407 if (resultsLeft.testAll() && resultsRight.testAll() && resultsBase.testAll()) { 408 //enable button 409 String strSuccess = getResources().getString(R.string.audio_general_test_passed); 410 appendResultsToScreen(strSuccess); 411 } else { 412 String strFailed = getResources().getString(R.string.audio_general_test_failed); 413 appendResultsToScreen(strFailed + "\n"); 414 String strWarning = getResources().getString(R.string.audio_general_deficiency_found); 415 appendResultsToScreen(strWarning); 416 } 417 getPassButton().setEnabled(true); //Everybody passes! (for now...) 418 } 419 computeResultsForVector(VectorAverage freqAverage,Results results, boolean isBase, AudioBandSpecs[] bandSpecs)420 private void computeResultsForVector(VectorAverage freqAverage,Results results, boolean isBase, 421 AudioBandSpecs[] bandSpecs) { 422 423 results.mIsBaseMeasurement = isBase; 424 int points = freqAverage.getSize(); 425 if (points > 0) { 426 //compute vector in db 427 double[] values = new double[points]; 428 freqAverage.getData(values, false); 429 results.mValuesLog = new double[points]; 430 for (int i = 0; i < points; i++) { 431 results.mValuesLog[i] = 20 * Math.log10(values[i]); 432 } 433 434 int currentBand = 0; 435 for (int i = 0; i < points; i++) { 436 double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples; 437 if (freq > bandSpecs[currentBand].mFreqStop) { 438 currentBand++; 439 if (currentBand >= mBands) 440 break; 441 } 442 443 if (freq >= bandSpecs[currentBand].mFreqStart) { 444 results.mAverageEnergyPerBand[currentBand] += results.mValuesLog[i]; 445 results.mPointsPerBand[currentBand]++; 446 } 447 } 448 449 for (int b = 0; b < mBands; b++) { 450 if (results.mPointsPerBand[b] > 0) { 451 results.mAverageEnergyPerBand[b] = 452 results.mAverageEnergyPerBand[b] / results.mPointsPerBand[b]; 453 } 454 } 455 456 //set offset relative to band 1 level 457 for (int b = 0; b < mBands; b++) { 458 bandSpecs[b].setOffset(results.mAverageEnergyPerBand[1]); 459 } 460 461 //test points in band. 462 currentBand = 0; 463 for (int i = 0; i < points; i++) { 464 double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples; 465 if (freq > bandSpecs[currentBand].mFreqStop) { 466 currentBand++; 467 if (currentBand >= mBands) 468 break; 469 } 470 471 if (freq >= bandSpecs[currentBand].mFreqStart) { 472 double value = results.mValuesLog[i]; 473 if (bandSpecs[currentBand].isInBounds(freq, value)) { 474 results.mInBoundPointsPerBand[currentBand]++; 475 } 476 } 477 } 478 479 appendResultsToScreen(results.toString()); 480 //store results 481 recordTestResults(results); 482 } else { 483 appendResultsToScreen("Failed testing channel " + results.mLabel); 484 } 485 } 486 487 //append results appendResultsToScreen(String str)488 private void appendResultsToScreen(String str) { 489 String currentText = mResultText.getText().toString(); 490 mResultText.setText(currentText + "\n" + str); 491 } 492 493 /** 494 * Store test results in log 495 */ recordTestResults(Results results)496 private void recordTestResults(Results results) { 497 String channelLabel = "channel_" + results.mLabel; 498 499 for (int b = 0; b < mBands; b++) { 500 String bandLabel = String.format(channelLabel + "_%d", b); 501 getReportLog().addValue( 502 bandLabel + "_Level", 503 results.mAverageEnergyPerBand[b], 504 ResultType.HIGHER_BETTER, 505 ResultUnit.NONE); 506 507 getReportLog().addValue( 508 bandLabel + "_pointsinbound", 509 results.mInBoundPointsPerBand[b], 510 ResultType.HIGHER_BETTER, 511 ResultUnit.COUNT); 512 513 getReportLog().addValue( 514 bandLabel + "_pointstotal", 515 results.mPointsPerBand[b], 516 ResultType.NEUTRAL, 517 ResultUnit.COUNT); 518 } 519 520 getReportLog().addValues(channelLabel + "_magnitudeSpectrumLog", 521 results.mValuesLog, 522 ResultType.NEUTRAL, 523 ResultUnit.NONE); 524 525 Log.v(TAG, "Results Recorded"); 526 } 527 startRecording()528 private void startRecording() { 529 synchronized (mRecordingLock) { 530 mIsRecording = true; 531 } 532 533 boolean successful = initRecord(); 534 if (successful) { 535 startRecordingForReal(); 536 } else { 537 Log.v(TAG, "Recorder initialization error."); 538 synchronized (mRecordingLock) { 539 mIsRecording = false; 540 } 541 } 542 } 543 startRecordingForReal()544 private void startRecordingForReal() { 545 // start streaming 546 if (mRecordThread == null) { 547 mRecordThread = new Thread(AudioFrequencySpeakerActivity.this); 548 mRecordThread.setName("FrequencyAnalyzerThread"); 549 mRecordThreadShutdown = false; 550 } 551 if (!mRecordThread.isAlive()) { 552 mRecordThread.start(); 553 } 554 555 mPipe.flush(); 556 557 long startTime = SystemClock.uptimeMillis(); 558 mRecorder.startRecording(); 559 if (mRecorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) { 560 stopRecording(); 561 return; 562 } 563 Log.v(TAG, "Start time: " + (long) (SystemClock.uptimeMillis() - startTime) + " ms"); 564 } 565 stopRecording()566 private void stopRecording() { 567 synchronized (mRecordingLock) { 568 stopRecordingForReal(); 569 mIsRecording = false; 570 } 571 } 572 stopRecordingForReal()573 private void stopRecordingForReal() { 574 575 // stop streaming 576 Thread zeThread = mRecordThread; 577 mRecordThread = null; 578 mRecordThreadShutdown = true; 579 if (zeThread != null) { 580 zeThread.interrupt(); 581 try { 582 zeThread.join(); 583 } catch(InterruptedException e) { 584 Log.v(TAG,"Error shutting down recording thread " + e); 585 //we don't really care about this error, just logging it. 586 } 587 } 588 // release recording resources 589 if (mRecorder != null) { 590 mRecorder.stop(); 591 mRecorder.release(); 592 mRecorder = null; 593 } 594 } 595 initRecord()596 private boolean initRecord() { 597 int minRecordBuffSizeInBytes = AudioRecord.getMinBufferSize(mSamplingRate, 598 mChannelConfig, mAudioFormat); 599 Log.v(TAG,"FrequencyAnalyzer: min buff size = " + minRecordBuffSizeInBytes + " bytes"); 600 if (minRecordBuffSizeInBytes <= 0) { 601 return false; 602 } 603 604 mMinRecordBufferSizeInSamples = minRecordBuffSizeInBytes / 2; 605 // allocate the byte array to read the audio data 606 607 mAudioShortArray = new short[mMinRecordBufferSizeInSamples]; 608 609 Log.v(TAG, "Initiating record:"); 610 Log.v(TAG, " using source " + mSelectedRecordSource); 611 Log.v(TAG, " at " + mSamplingRate + "Hz"); 612 613 try { 614 mRecorder = new AudioRecord(mSelectedRecordSource, mSamplingRate, 615 mChannelConfig, mAudioFormat, 2 * minRecordBuffSizeInBytes); 616 } catch (IllegalArgumentException e) { 617 return false; 618 } 619 if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) { 620 mRecorder.release(); 621 mRecorder = null; 622 return false; 623 } 624 mRecorder.setRecordPositionUpdateListener(this); 625 mRecorder.setPositionNotificationPeriod(mBlockSizeSamples / 2); 626 return true; 627 } 628 629 // --------------------------------------------------------- 630 // Implementation of AudioRecord.OnPeriodicNotificationListener 631 // -------------------- onPeriodicNotification(AudioRecord recorder)632 public void onPeriodicNotification(AudioRecord recorder) { 633 int samplesAvailable = mPipe.availableToRead(); 634 int samplesNeeded = mBlockSizeSamples; 635 if (samplesAvailable >= samplesNeeded) { 636 mPipe.read(mAudioShortArray2, 0, samplesNeeded); 637 638 //compute stuff. 639 double maxval = Math.pow(2, 15); 640 int clipcount = 0; 641 double cliplevel = (maxval-10) / maxval; 642 double sum = 0; 643 double maxabs = 0; 644 int i; 645 int index = 0; 646 647 for (i = 0; i < samplesNeeded; i++) { 648 double value = mAudioShortArray2[i] / maxval; 649 double valueabs = Math.abs(value); 650 651 if (valueabs > maxabs) { 652 maxabs = valueabs; 653 } 654 655 if (valueabs > cliplevel) { 656 clipcount++; 657 } 658 659 sum += value * value; 660 //fft stuff 661 if (index < mBlockSizeSamples) { 662 mData.mData[index] = value; 663 } 664 index++; 665 } 666 667 //for the current frame, compute FFT and send to the viewer. 668 669 //apply window and pack as complex for now. 670 DspBufferMath.mult(mData, mData, mWindow.mBuffer); 671 DspBufferMath.set(mC, mData); 672 mFftServer.fft(mC, 1); 673 674 double[] halfMagnitude = new double[mBlockSizeSamples / 2]; 675 for (i = 0; i < mBlockSizeSamples / 2; i++) { 676 halfMagnitude[i] = Math.sqrt(mC.mReal[i] * mC.mReal[i] + mC.mImag[i] * mC.mImag[i]); 677 } 678 679 mFreqAverageMain.setData(halfMagnitude, false); //average all of them! 680 681 switch(mCurrentTest) { 682 case 0: 683 mFreqAverageBase.setData(halfMagnitude, false); 684 break; 685 case 1: 686 mFreqAverageLeft.setData(halfMagnitude, false); 687 break; 688 case 2: 689 mFreqAverageRight.setData(halfMagnitude, false); 690 break; 691 } 692 } 693 } 694 onMarkerReached(AudioRecord track)695 public void onMarkerReached(AudioRecord track) { 696 } 697 698 // --------------------------------------------------------- 699 // Implementation of Runnable for the audio recording + playback 700 // -------------------- run()701 public void run() { 702 int nSamplesRead = 0; 703 704 Thread thisThread = Thread.currentThread(); 705 while (mRecordThread == thisThread && !mRecordThreadShutdown) { 706 // read from native recorder 707 nSamplesRead = mRecorder.read(mAudioShortArray, 0, mMinRecordBufferSizeInSamples); 708 if (nSamplesRead > 0) { 709 mPipe.write(mAudioShortArray, 0, nSamplesRead); 710 } 711 } 712 } 713 testUSB()714 private void testUSB() { 715 boolean isConnected = UsbMicrophoneTester.getIsMicrophoneConnected(getApplicationContext()); 716 mUsbDevicesInfo = UsbMicrophoneTester.getUSBDeviceListString(getApplicationContext()); 717 718 if (isConnected) { 719 mUsbStatusText.setText( 720 getResources().getText(R.string.audio_frequency_speaker_mic_ready_text)); 721 enableLayout(true); 722 } else { 723 mUsbStatusText.setText( 724 getResources().getText(R.string.audio_frequency_speaker_mic_not_ready_text)); 725 enableLayout(false); 726 } 727 } 728 729 } 730