1 /* 2 * Copyright 2017 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.mobileer.oboetester; 18 19 import android.content.Context; 20 import android.media.AudioManager; 21 import android.media.audiofx.AcousticEchoCanceler; 22 import android.media.audiofx.AutomaticGainControl; 23 import android.media.audiofx.BassBoost; 24 import android.media.audiofx.LoudnessEnhancer; 25 import android.util.AttributeSet; 26 import android.view.LayoutInflater; 27 import android.view.View; 28 import android.widget.AdapterView; 29 import android.widget.ArrayAdapter; 30 import android.widget.CheckBox; 31 import android.widget.CompoundButton; 32 import android.widget.SeekBar; 33 import android.widget.Spinner; 34 import android.widget.TableRow; 35 import android.widget.TextView; 36 import android.widget.LinearLayout; 37 import android.util.Log; 38 39 import com.mobileer.audio_device.AudioDeviceListEntry; 40 import com.mobileer.audio_device.AudioDeviceSpinner; 41 42 /** 43 * View for Editing a requested StreamConfiguration 44 * and displaying the actual StreamConfiguration. 45 */ 46 47 public class StreamConfigurationView extends LinearLayout { 48 private static final String TAG = "StreamConfigurationView"; 49 50 protected Spinner mNativeApiSpinner; 51 private TextView mActualNativeApiView; 52 53 private TextView mActualMMapView; 54 private CheckBox mRequestedMMapView; 55 private TextView mActualExclusiveView; 56 private TextView mActualPerformanceView; 57 private Spinner mPerformanceSpinner; 58 private CheckBox mRequestedExclusiveView; 59 private CheckBox mChannelConversionBox; 60 private CheckBox mFormatConversionBox; 61 private Spinner mChannelCountSpinner; 62 private TextView mActualChannelCountView; 63 private Spinner mChannelMaskSpinner; 64 private TextView mActualChannelMaskView; 65 private TextView mActualFormatView; 66 67 private TableRow mInputPresetTableRow; 68 private Spinner mInputPresetSpinner; 69 private TextView mActualInputPresetView; 70 71 private TableRow mUsageTableRow; 72 private Spinner mUsageSpinner; 73 private TextView mActualUsageView; 74 75 private TableRow mContentTypeTableRow; 76 private Spinner mContentTypeSpinner; 77 private TextView mActualContentTypeView; 78 79 private Spinner mFormatSpinner; 80 private Spinner mSampleRateSpinner; 81 private Spinner mRateConversionQualitySpinner; 82 private TextView mActualSampleRateView; 83 private LinearLayout mHideableView; 84 85 private AudioDeviceSpinner mDeviceSpinner; 86 private TextView mActualSessionIdView; 87 private CheckBox mRequestAudioEffect; 88 89 private TextView mStreamInfoView; 90 private TextView mStreamStatusView; 91 private TextView mOptionExpander; 92 private String mHideSettingsText; 93 private String mShowSettingsText; 94 95 private LinearLayout mInputEffectsLayout; 96 private LinearLayout mOutputEffectsLayout; 97 98 private CheckBox mAutomaticGainControlCheckBox; 99 private CheckBox mAcousticEchoCancelerCheckBox; 100 private TextView mBassBoostTextView; 101 private SeekBar mBassBoostSeekBar; 102 private TextView mLoudnessEnhancerTextView; 103 private SeekBar mLoudnessEnhancerSeekBar; 104 105 private boolean mIsChannelMaskLastSelected; 106 107 private boolean misOutput; 108 109 private BassBoost mBassBoost; 110 private LoudnessEnhancer mLoudnessEnhancer; 111 private AcousticEchoCanceler mAcousticEchoCanceler; 112 private AutomaticGainControl mAutomaticGainControl; 113 114 // Create an anonymous implementation of OnClickListener 115 private View.OnClickListener mToggleListener = new View.OnClickListener() { 116 public void onClick(View v) { 117 if (mHideableView.isShown()) { 118 hideSettingsView(); 119 } else { 120 showSettingsView(); 121 } 122 } 123 }; 124 yesOrNo(boolean b)125 public static String yesOrNo(boolean b) { 126 return b ? "YES" : "NO"; 127 } 128 updateSettingsViewText()129 private void updateSettingsViewText() { 130 if (mHideableView.isShown()) { 131 mOptionExpander.setText(mHideSettingsText); 132 } else { 133 mOptionExpander.setText(mShowSettingsText); 134 } 135 } 136 showSettingsView()137 public void showSettingsView() { 138 mHideableView.setVisibility(View.VISIBLE); 139 updateSettingsViewText(); 140 } 141 hideSampleRateMenu()142 public void hideSampleRateMenu() { 143 if (mSampleRateSpinner != null) { 144 mSampleRateSpinner.setVisibility(View.GONE); 145 } 146 } 147 hideSettingsView()148 public void hideSettingsView() { 149 mHideableView.setVisibility(View.GONE); 150 updateSettingsViewText(); 151 } 152 StreamConfigurationView(Context context)153 public StreamConfigurationView(Context context) { 154 super(context); 155 initializeViews(context); 156 } 157 StreamConfigurationView(Context context, AttributeSet attrs)158 public StreamConfigurationView(Context context, AttributeSet attrs) { 159 super(context, attrs); 160 initializeViews(context); 161 } 162 StreamConfigurationView(Context context, AttributeSet attrs, int defStyle)163 public StreamConfigurationView(Context context, 164 AttributeSet attrs, 165 int defStyle) { 166 super(context, attrs, defStyle); 167 initializeViews(context); 168 } 169 170 /** 171 * Inflates the views in the layout. 172 * 173 * @param context 174 * the current context for the view. 175 */ initializeViews(Context context)176 private void initializeViews(Context context) { 177 LayoutInflater inflater = (LayoutInflater) context 178 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 179 inflater.inflate(R.layout.stream_config, this); 180 181 mHideSettingsText = getResources().getString(R.string.hint_hide_settings); 182 mShowSettingsText = getResources().getString(R.string.hint_show_settings); 183 184 mHideableView = (LinearLayout) findViewById(R.id.hideableView); 185 186 mOptionExpander = (TextView) findViewById(R.id.toggle_stream_config); 187 mOptionExpander.setOnClickListener(mToggleListener); 188 189 mNativeApiSpinner = (Spinner) findViewById(R.id.spinnerNativeApi); 190 mNativeApiSpinner.setSelection(StreamConfiguration.NATIVE_API_UNSPECIFIED); 191 192 mActualNativeApiView = (TextView) findViewById(R.id.actualNativeApi); 193 194 mChannelConversionBox = (CheckBox) findViewById(R.id.checkChannelConversion); 195 196 mFormatConversionBox = (CheckBox) findViewById(R.id.checkFormatConversion); 197 198 mActualMMapView = (TextView) findViewById(R.id.actualMMap); 199 mRequestedMMapView = (CheckBox) findViewById(R.id.requestedMMapEnable); 200 boolean mmapSupported = NativeEngine.isMMapSupported(); 201 mRequestedMMapView.setEnabled(mmapSupported); 202 mRequestedMMapView.setChecked(mmapSupported); 203 204 mActualExclusiveView = (TextView) findViewById(R.id.actualExclusiveMode); 205 mRequestedExclusiveView = (CheckBox) findViewById(R.id.requestedExclusiveMode); 206 207 boolean mmapExclusiveSupported = NativeEngine.isMMapExclusiveSupported(); 208 mRequestedExclusiveView.setEnabled(mmapExclusiveSupported); 209 mRequestedExclusiveView.setChecked(mmapExclusiveSupported); 210 211 mActualSessionIdView = (TextView) findViewById(R.id.sessionId); 212 mRequestAudioEffect = (CheckBox) findViewById(R.id.requestAudioEffect); 213 214 mOutputEffectsLayout = (LinearLayout) findViewById(R.id.outputEffects); 215 mInputEffectsLayout = (LinearLayout) findViewById(R.id.inputEffects); 216 217 mRequestAudioEffect.setOnClickListener(new View.OnClickListener() { 218 @Override 219 public void onClick(View view) { 220 onRequestAudioEffectClicked(((CheckBox) view).isChecked()); 221 } 222 }); 223 224 mAutomaticGainControlCheckBox = (CheckBox) findViewById(R.id.checkBoxAutomaticGainControl); 225 mAcousticEchoCancelerCheckBox = (CheckBox) findViewById(R.id.checkBoxAcousticEchoCanceler); 226 mBassBoostTextView = (TextView) findViewById(R.id.textBassBoost); 227 mBassBoostSeekBar = (SeekBar) findViewById(R.id.seekBarBassBoost); 228 mLoudnessEnhancerTextView = (TextView) findViewById(R.id.textLoudnessEnhancer); 229 mLoudnessEnhancerSeekBar = (SeekBar) findViewById(R.id.seekBarLoudnessEnhancer); 230 231 mAutomaticGainControlCheckBox.setEnabled(AutomaticGainControl.isAvailable()); 232 mAcousticEchoCancelerCheckBox.setEnabled(AcousticEchoCanceler.isAvailable()); 233 234 mBassBoostSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 235 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 236 onBassBoostSeekBarChanged(progress); 237 } 238 239 @Override 240 public void onStartTrackingTouch(SeekBar seekBar) { 241 } 242 243 @Override 244 public void onStopTrackingTouch(SeekBar seekBar) { 245 } 246 }); 247 248 mLoudnessEnhancerSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 249 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 250 onLoudnessEnhancerSeekBarChanged(progress); 251 } 252 253 @Override 254 public void onStartTrackingTouch(SeekBar seekBar) { 255 } 256 257 @Override 258 public void onStopTrackingTouch(SeekBar seekBar) { 259 } 260 }); 261 262 mAutomaticGainControlCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 263 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 264 onAutomaticGainControlCheckBoxChanged(isChecked); 265 } 266 }); 267 268 mAcousticEchoCancelerCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 269 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 270 onAcousticEchoCancelerCheckBoxChanged(isChecked); 271 } 272 }); 273 274 mActualSampleRateView = (TextView) findViewById(R.id.actualSampleRate); 275 mSampleRateSpinner = (Spinner) findViewById(R.id.spinnerSampleRate); 276 mActualChannelCountView = (TextView) findViewById(R.id.actualChannelCount); 277 mChannelCountSpinner = (Spinner) findViewById(R.id.spinnerChannelCount); 278 mChannelCountSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 279 @Override 280 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 281 onChannelCountSpinnerSelected(); 282 } 283 284 @Override 285 public void onNothingSelected(AdapterView<?> adapterView) { 286 // no-op 287 } 288 }); 289 mActualFormatView = (TextView) findViewById(R.id.actualAudioFormat); 290 mFormatSpinner = (Spinner) findViewById(R.id.spinnerFormat); 291 mRateConversionQualitySpinner = (Spinner) findViewById(R.id.spinnerSRCQuality); 292 293 mActualPerformanceView = (TextView) findViewById(R.id.actualPerformanceMode); 294 mPerformanceSpinner = (Spinner) findViewById(R.id.spinnerPerformanceMode); 295 mPerformanceSpinner.setSelection(StreamConfiguration.PERFORMANCE_MODE_LOW_LATENCY 296 - StreamConfiguration.PERFORMANCE_MODE_NONE); 297 298 mInputPresetTableRow = (TableRow) findViewById(R.id.rowInputPreset); 299 mActualInputPresetView = (TextView) findViewById(R.id.actualInputPreset); 300 mInputPresetSpinner = (Spinner) findViewById(R.id.spinnerInputPreset); 301 mInputPresetSpinner.setSelection(2); // TODO need better way to select voice recording default 302 303 mUsageTableRow = (TableRow) findViewById(R.id.rowUsage); 304 mActualUsageView = (TextView) findViewById(R.id.actualUsage); 305 mUsageSpinner = (Spinner) findViewById(R.id.spinnerUsage); 306 307 mContentTypeTableRow = (TableRow) findViewById(R.id.rowContentType); 308 mActualContentTypeView = (TextView) findViewById(R.id.actualContentType); 309 mContentTypeSpinner = (Spinner) findViewById(R.id.spinnerContentType); 310 311 mStreamInfoView = (TextView) findViewById(R.id.streamInfo); 312 313 mStreamStatusView = (TextView) findViewById(R.id.statusView); 314 315 mDeviceSpinner = (AudioDeviceSpinner) findViewById(R.id.devices_spinner); 316 317 mActualChannelMaskView = (TextView) findViewById(R.id.actualChannelMask); 318 mChannelMaskSpinner = (Spinner) findViewById(R.id.spinnerChannelMask); 319 ArrayAdapter<String> channelMaskSpinnerArrayAdapter = new ArrayAdapter<String>(context, 320 android.R.layout.simple_spinner_item, 321 StreamConfiguration.getAllChannelMasks()); 322 mChannelMaskSpinner.setAdapter(channelMaskSpinnerArrayAdapter); 323 mChannelMaskSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 324 @Override 325 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 326 onChannelMaskSpinnerSelected(); 327 } 328 329 @Override 330 public void onNothingSelected(AdapterView<?> adapterView) { 331 // no-op 332 } 333 }); 334 335 showSettingsView(); 336 } 337 setOutput(boolean output)338 public void setOutput(boolean output) { 339 misOutput = output; 340 String ioText; 341 if (output) { 342 mDeviceSpinner.setDirectionType(AudioManager.GET_DEVICES_OUTPUTS); 343 ioText = "OUTPUT"; 344 } else { 345 mDeviceSpinner.setDirectionType(AudioManager.GET_DEVICES_INPUTS); 346 ioText = "INPUT"; 347 } 348 mHideSettingsText = getResources().getString(R.string.hint_hide_settings) + " - " + ioText; 349 mShowSettingsText = getResources().getString(R.string.hint_show_settings) + " - " + ioText; 350 updateSettingsViewText(); 351 352 // Don't show InputPresets for output streams. 353 mInputPresetTableRow.setVisibility(output ? View.GONE : View.VISIBLE); 354 // Don't show Usage and Content Type for input streams. 355 mUsageTableRow.setVisibility(output ? View.VISIBLE : View.GONE); 356 mContentTypeTableRow.setVisibility(output ? View.VISIBLE : View.GONE); 357 } 358 applyToModel(StreamConfiguration config)359 public void applyToModel(StreamConfiguration config) { 360 // Menu position matches actual enum value for these properties. 361 config.setNativeApi(mNativeApiSpinner.getSelectedItemPosition()); 362 config.setFormat(mFormatSpinner.getSelectedItemPosition()); 363 config.setRateConversionQuality(mRateConversionQualitySpinner.getSelectedItemPosition()); 364 365 int id = ((AudioDeviceListEntry) mDeviceSpinner.getSelectedItem()).getId(); 366 config.setDeviceId(id); 367 368 String text = mSampleRateSpinner.getSelectedItem().toString(); 369 int sampleRate = Integer.parseInt(text); 370 config.setSampleRate(sampleRate); 371 372 text = mInputPresetSpinner.getSelectedItem().toString(); 373 int inputPreset = StreamConfiguration.convertTextToInputPreset(text); 374 config.setInputPreset(inputPreset); 375 376 text = mUsageSpinner.getSelectedItem().toString(); 377 int usage = StreamConfiguration.convertTextToUsage(text); 378 config.setUsage(usage); 379 380 text = mContentTypeSpinner.getSelectedItem().toString(); 381 int contentType = StreamConfiguration.convertTextToContentType(text); 382 config.setContentType(contentType); 383 384 // The corresponding channel count of the selected channel mask may be different from 385 // the selected channel count, the last selected will be respected. 386 if (mIsChannelMaskLastSelected) { 387 text = mChannelMaskSpinner.getSelectedItem().toString(); 388 int channelMask = StreamConfiguration.convertTextToChannelMask(text); 389 config.setChannelMask(channelMask); 390 config.setChannelCount(0); 391 Log.d(TAG, String.format("Set channel mask as %s(%#x)", text, channelMask)); 392 } else { 393 config.setChannelCount(mChannelCountSpinner.getSelectedItemPosition()); 394 config.setChannelMask(StreamConfiguration.UNSPECIFIED); 395 Log.d(TAG, "Set channel count as " + mChannelCountSpinner.getSelectedItemPosition()); 396 } 397 398 config.setMMap(mRequestedMMapView.isChecked()); 399 config.setChannelConversionAllowed(mChannelConversionBox.isChecked()); 400 config.setFormatConversionAllowed(mFormatConversionBox.isChecked()); 401 config.setSharingMode(mRequestedExclusiveView.isChecked() 402 ? StreamConfiguration.SHARING_MODE_EXCLUSIVE 403 : StreamConfiguration.SHARING_MODE_SHARED); 404 config.setSessionId(mRequestAudioEffect.isChecked() 405 ? StreamConfiguration.SESSION_ID_ALLOCATE 406 : StreamConfiguration.SESSION_ID_NONE); 407 408 config.setPerformanceMode(mPerformanceSpinner.getSelectedItemPosition() 409 + StreamConfiguration.PERFORMANCE_MODE_NONE); 410 } 411 setChildrenEnabled(boolean enabled)412 public void setChildrenEnabled(boolean enabled) { 413 mNativeApiSpinner.setEnabled(enabled); 414 mPerformanceSpinner.setEnabled(enabled); 415 mRequestedMMapView.setEnabled(enabled && NativeEngine.isMMapSupported()); 416 mRequestedExclusiveView.setEnabled(enabled && NativeEngine.isMMapExclusiveSupported()); 417 mChannelConversionBox.setEnabled(enabled); 418 mFormatConversionBox.setEnabled(enabled); 419 mChannelCountSpinner.setEnabled(enabled); 420 mChannelMaskSpinner.setEnabled(enabled); 421 mInputPresetSpinner.setEnabled(enabled); 422 mUsageSpinner.setEnabled(enabled); 423 mContentTypeSpinner.setEnabled(enabled); 424 mFormatSpinner.setEnabled(enabled); 425 mSampleRateSpinner.setEnabled(enabled); 426 mRateConversionQualitySpinner.setEnabled(enabled); 427 mDeviceSpinner.setEnabled(enabled); 428 mRequestAudioEffect.setEnabled(enabled); 429 } 430 431 // This must be called on the UI thread. updateDisplay(StreamConfiguration actualConfiguration)432 void updateDisplay(StreamConfiguration actualConfiguration) { 433 int value; 434 435 value = actualConfiguration.getNativeApi(); 436 mActualNativeApiView.setText(StreamConfiguration.convertNativeApiToText(value)); 437 438 mActualMMapView.setText(yesOrNo(actualConfiguration.isMMap())); 439 int sharingMode = actualConfiguration.getSharingMode(); 440 boolean isExclusive = (sharingMode == StreamConfiguration.SHARING_MODE_EXCLUSIVE); 441 mActualExclusiveView.setText(yesOrNo(isExclusive)); 442 443 value = actualConfiguration.getPerformanceMode(); 444 mActualPerformanceView.setText(StreamConfiguration.convertPerformanceModeToText(value)); 445 mActualPerformanceView.requestLayout(); 446 447 value = actualConfiguration.getFormat(); 448 mActualFormatView.setText(StreamConfiguration.convertFormatToText(value)); 449 mActualFormatView.requestLayout(); 450 451 value = actualConfiguration.getInputPreset(); 452 mActualInputPresetView.setText(StreamConfiguration.convertInputPresetToText(value)); 453 mActualInputPresetView.requestLayout(); 454 455 value = actualConfiguration.getUsage(); 456 mActualUsageView.setText(StreamConfiguration.convertUsageToText(value)); 457 mActualUsageView.requestLayout(); 458 459 value = actualConfiguration.getContentType(); 460 mActualContentTypeView.setText(StreamConfiguration.convertContentTypeToText(value)); 461 mActualContentTypeView.requestLayout(); 462 463 mActualChannelCountView.setText(actualConfiguration.getChannelCount() + ""); 464 mActualSampleRateView.setText(actualConfiguration.getSampleRate() + ""); 465 mActualSessionIdView.setText("S#: " + actualConfiguration.getSessionId()); 466 value = actualConfiguration.getChannelMask(); 467 mActualChannelMaskView.setText(StreamConfiguration.convertChannelMaskToText(value)); 468 469 boolean isMMap = actualConfiguration.isMMap(); 470 mStreamInfoView.setText("burst = " + actualConfiguration.getFramesPerBurst() 471 + ", capacity = " + actualConfiguration.getBufferCapacityInFrames() 472 + ", devID = " + actualConfiguration.getDeviceId() 473 + ", " + (actualConfiguration.isMMap() ? "MMAP" : "Legacy") 474 + (isMMap ? ", " + StreamConfiguration.convertSharingModeToText(sharingMode) : "") 475 ); 476 477 mHideableView.requestLayout(); 478 } 479 480 // This must be called on the UI thread. setStatusText(String msg)481 public void setStatusText(String msg) { 482 mStreamStatusView.setText(msg); 483 } 484 setExclusiveMode(boolean b)485 public void setExclusiveMode(boolean b) { 486 mRequestedExclusiveView.setChecked(b); 487 } 488 setFormat(int format)489 public void setFormat(int format) { 490 mFormatSpinner.setSelection(format); // position matches format 491 } 492 setFormatConversionAllowed(boolean allowed)493 public void setFormatConversionAllowed(boolean allowed) { 494 mFormatConversionBox.setChecked(allowed); 495 } 496 onChannelCountSpinnerSelected()497 private void onChannelCountSpinnerSelected() { 498 mIsChannelMaskLastSelected = false; 499 } 500 onChannelMaskSpinnerSelected()501 private void onChannelMaskSpinnerSelected() { 502 mIsChannelMaskLastSelected = true; 503 } 504 onRequestAudioEffectClicked(boolean isChecked)505 private void onRequestAudioEffectClicked(boolean isChecked) { 506 if (isChecked){ 507 if (misOutput) { 508 mOutputEffectsLayout.setVisibility(VISIBLE); 509 } else { 510 mInputEffectsLayout.setVisibility(VISIBLE); 511 } 512 } else { 513 if (misOutput) { 514 mOutputEffectsLayout.setVisibility(GONE); 515 } else { 516 mInputEffectsLayout.setVisibility(GONE); 517 } 518 } 519 } 520 setupEffects(int sessionId)521 public void setupEffects(int sessionId) { 522 if (misOutput) { 523 mBassBoost = new BassBoost(0, sessionId); 524 mBassBoost.setStrength((short) mBassBoostSeekBar.getProgress()); 525 mLoudnessEnhancer = new LoudnessEnhancer(sessionId); 526 mLoudnessEnhancer.setTargetGain((short) mLoudnessEnhancerSeekBar.getProgress()); 527 } else { 528 // If AEC is not available, the checkbox will be disabled in initializeViews(). 529 if (mAcousticEchoCancelerCheckBox.isEnabled()) { 530 mAcousticEchoCanceler = AcousticEchoCanceler.create(sessionId); 531 if (mAcousticEchoCanceler != null) { 532 mAcousticEchoCanceler.setEnabled(mAcousticEchoCancelerCheckBox.isChecked()); 533 } else { 534 Log.e(TAG, String.format("Could not create AcousticEchoCanceler")); 535 } 536 } 537 // If AGC is not available, the checkbox will be disabled in initializeViews(). 538 if (mAutomaticGainControlCheckBox.isEnabled()) { 539 mAutomaticGainControl = AutomaticGainControl.create(sessionId); 540 if (mAutomaticGainControl != null) { 541 mAutomaticGainControl.setEnabled(mAutomaticGainControlCheckBox.isChecked()); 542 } else { 543 Log.e(TAG, String.format("Could not create AutomaticGainControl")); 544 } 545 } 546 } 547 } 548 onLoudnessEnhancerSeekBarChanged(int progress)549 private void onLoudnessEnhancerSeekBarChanged(int progress) { 550 if (mLoudnessEnhancer != null) { 551 mLoudnessEnhancer.setTargetGain(progress); 552 } 553 mLoudnessEnhancerTextView.setText("Loudness Enhancer: " + progress); 554 } 555 onBassBoostSeekBarChanged(int progress)556 private void onBassBoostSeekBarChanged(int progress) { 557 if (mBassBoost != null) { 558 mBassBoost.setStrength((short) progress); 559 } 560 mBassBoostTextView.setText("Bass Boost: " + progress); 561 } 562 onAutomaticGainControlCheckBoxChanged(boolean isChecked)563 private void onAutomaticGainControlCheckBoxChanged(boolean isChecked) { 564 if (mAutomaticGainControlCheckBox.isEnabled() && mAutomaticGainControl != null) { 565 mAutomaticGainControl.setEnabled(isChecked); 566 } 567 } 568 onAcousticEchoCancelerCheckBoxChanged(boolean isChecked)569 private void onAcousticEchoCancelerCheckBoxChanged(boolean isChecked) { 570 if (mAcousticEchoCancelerCheckBox.isEnabled() && mAcousticEchoCanceler != null) { 571 mAcousticEchoCanceler.setEnabled(isChecked); 572 } 573 } 574 } 575