blob: 29026fa02ce326b6f810cb44a9519a6f1dd87891 [file] [log] [blame]
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.sample.oboe.manualtest;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.IOException;
/**
* Activity to capture audio and then send a delayed copy to output.
* There is a fader for setting delay time
*/
public class EchoActivity extends TestInputActivity {
AudioOutputTester mAudioOutTester;
protected TextView mTextDelayTime;
protected SeekBar mFaderDelayTime;
protected ExponentialTaper mTaperDelayTime;
private static final double MIN_DELAY_TIME_SECONDS = 0.0;
private static final double MAX_DELAY_TIME_SECONDS = 3.0;
private double mDelayTime;
private Button mStartButton;
private Button mStopButton;
private TextView mStatusTextView;
private ColdStartSniffer mNativeSniffer = new ColdStartSniffer(this);
protected static final int MAX_DELAY_TIME_PROGRESS = 1000;
private SeekBar.OnSeekBarChangeListener mDelayListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
setDelayTimeByPosition(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
// Periodically query for cold start latency from the native code until it is ready.
protected class ColdStartSniffer extends NativeSniffer {
private int stableCallCount = 0;
private static final int STABLE_CALLS_NEEDED = 20;
private int mInputLatency;
private int mOutputLatency;
public ColdStartSniffer(Activity activity) {
super(activity);
}
@Override
public void startSniffer() {
stableCallCount = 0;
mInputLatency = -1;
mOutputLatency = -1;
super.startSniffer();
}
public void run() {
mInputLatency = getColdStartInputMillis();
mOutputLatency = getColdStartOutputMillis();
updateStatusText();
if (!isComplete()) {
reschedule();
}
}
private boolean isComplete() {
if (mInputLatency > 0 && mOutputLatency > 0) {
stableCallCount++;
}
return stableCallCount > STABLE_CALLS_NEEDED;
}
private String getCurrentStatusReport() {
StringBuffer message = new StringBuffer();
message.append("cold.start.input.msec = " +
((mInputLatency > 0)
? mInputLatency
: "?")
+ "\n");
message.append("cold.start.output.msec = " +
((mOutputLatency > 0)
? mOutputLatency
: "?")
+ "\n");
message.append("stable.call.count = " + stableCallCount + "\n");
return message.toString();
}
@Override
public String getShortReport() {
return getCurrentStatusReport();
}
@Override
public void updateStatusText() {
String message = getCurrentStatusReport();
mStatusTextView.setText(message);
}
}
private native int getColdStartInputMillis();
private native int getColdStartOutputMillis();
@Override
protected void inflateActivity() {
setContentView(R.layout.activity_echo);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updateEnabledWidgets();
mAudioOutTester = addAudioOutputTester();
mStartButton = (Button) findViewById(R.id.button_start_echo);
mStopButton = (Button) findViewById(R.id.button_stop_echo);
mStopButton.setEnabled(false);
mStatusTextView = (TextView) findViewById(R.id.text_status);
mTextDelayTime = (TextView) findViewById(R.id.text_delay_time);
mFaderDelayTime = (SeekBar) findViewById(R.id.fader_delay_time);
mFaderDelayTime.setOnSeekBarChangeListener(mDelayListener);
mTaperDelayTime = new ExponentialTaper(
MIN_DELAY_TIME_SECONDS,
MAX_DELAY_TIME_SECONDS,
100.0);
mFaderDelayTime.setProgress(MAX_DELAY_TIME_PROGRESS / 2);
hideSettingsViews();
}
private void setDelayTimeByPosition(int progress) {
mDelayTime = mTaperDelayTime.linearToExponential(
((double)progress)/MAX_DELAY_TIME_PROGRESS);
setDelayTime(mDelayTime);
mTextDelayTime.setText("DelayLine: " + (int)(mDelayTime * 1000) + " (msec)");
}
private native void setDelayTime(double delayTimeSeconds);
int getActivityType() {
return ACTIVITY_ECHO;
}
@Override
protected void resetConfiguration() {
super.resetConfiguration();
mAudioOutTester.reset();
}
public void onStartEcho(View view) {
try {
openAudio();
startAudio();
setDelayTime(mDelayTime);
mStartButton.setEnabled(false);
mStopButton.setEnabled(true);
keepScreenOn(true);
mNativeSniffer.startSniffer();
} catch (IOException e) {
showErrorToast(e.getMessage());
}
}
public void onStopEcho(View view) {
mNativeSniffer.stopSniffer();
stopAudio();
closeAudio();
mStartButton.setEnabled(true);
mStopButton.setEnabled(false);
keepScreenOn(false);
}
@Override
boolean isOutput() {
return false;
}
@Override
public void setupEffects(int sessionId) {
}
}