blob: e64f4e5785c83f90190153078bb2d06a049bcc5f [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.effectstest;
import android.media.audiofx.Visualizer;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
// This class only has `final' members, thus any thread-safety concerns
// can only come from the Visualizer effect class.
class VisualizerInstanceSync implements VisualizerInstance {
private static final String TAG = "VisualizerInstance";
private final Handler mUiHandler;
private final Visualizer mVisualizer;
private final VisualizerTestHandler mVisualizerTestHandler;
private final VisualizerListener mVisualizerListener;
VisualizerInstanceSync(int session, Handler uiHandler) {
mUiHandler = uiHandler;
try {
mVisualizer = new Visualizer(session);
} catch (UnsupportedOperationException e) {
Log.e(TAG, "Visualizer library not loaded");
throw new RuntimeException("Cannot initialize effect");
} catch (RuntimeException e) {
throw e;
}
mVisualizerTestHandler = new VisualizerTestHandler();
mVisualizerListener = new VisualizerListener();
}
// Not a "deep" copy, only copies the references.
VisualizerInstanceSync(VisualizerInstanceSync other) {
mUiHandler = other.mUiHandler;
mVisualizer = other.mVisualizer;
mVisualizerTestHandler = other.mVisualizerTestHandler;
mVisualizerListener = other.mVisualizerListener;
}
@Override
public void enableDataCaptureListener(boolean enable) {
mVisualizer.setDataCaptureListener(enable ? mVisualizerListener : null,
10000, enable, enable);
}
@Override
public boolean getEnabled() {
return mVisualizer.getEnabled();
}
@Override
public void release() {
mVisualizer.release();
Log.d(TAG, "Visualizer released");
}
@Override
public void setEnabled(boolean enabled) {
mVisualizer.setEnabled(enabled);
}
@Override
public void startStopCapture(boolean start) {
mVisualizerTestHandler.sendMessage(mVisualizerTestHandler.obtainMessage(
start ? MSG_START_CAPTURE : MSG_STOP_CAPTURE));
}
private static final int MSG_START_CAPTURE = 0;
private static final int MSG_STOP_CAPTURE = 1;
private static final int MSG_NEW_CAPTURE = 2;
private static final int CAPTURE_PERIOD_MS = 100;
private static int[] dataToMinMaxCenter(byte[] data, int len) {
int[] minMaxCenter = new int[3];
minMaxCenter[0] = data[0];
minMaxCenter[1] = data[len - 1];
minMaxCenter[2] = data[len / 2];
return minMaxCenter;
}
private class VisualizerTestHandler extends Handler {
private final int mCaptureSize;
private boolean mActive = false;
VisualizerTestHandler() {
mCaptureSize = mVisualizer.getCaptureSize();
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_START_CAPTURE:
if (!mActive) {
Log.d(TAG, "Start capture");
mActive = true;
sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE), CAPTURE_PERIOD_MS);
}
break;
case MSG_STOP_CAPTURE:
if (mActive) {
Log.d(TAG, "Stop capture");
mActive = false;
}
break;
case MSG_NEW_CAPTURE:
if (mActive) {
if (mCaptureSize > 0) {
byte[] data = new byte[mCaptureSize];
if (mVisualizer.getWaveForm(data) == Visualizer.SUCCESS) {
int len = data.length < mCaptureSize ? data.length : mCaptureSize;
mUiHandler.sendMessage(
mUiHandler.obtainMessage(
VisualizerTest.MSG_DISPLAY_WAVEFORM_VAL,
dataToMinMaxCenter(data, len)));
}
if (mVisualizer.getFft(data) == Visualizer.SUCCESS) {
int len = data.length < mCaptureSize ? data.length : mCaptureSize;
mUiHandler.sendMessage(
mUiHandler.obtainMessage(VisualizerTest.MSG_DISPLAY_FFT_VAL,
dataToMinMaxCenter(data, len)));
}
}
sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE), CAPTURE_PERIOD_MS);
}
break;
}
}
}
private class VisualizerListener implements Visualizer.OnDataCaptureListener {
@Override
public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform,
int samplingRate) {
if (visualizer == mVisualizer && waveform.length > 0) {
Log.d(TAG, "onWaveFormDataCapture(): " + waveform[0]
+ " smp rate: " + samplingRate / 1000);
mUiHandler.sendMessage(
mUiHandler.obtainMessage(VisualizerTest.MSG_DISPLAY_WAVEFORM_VAL,
dataToMinMaxCenter(waveform, waveform.length)));
}
}
@Override
public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
if (visualizer == mVisualizer && fft.length > 0) {
Log.d(TAG, "onFftDataCapture(): " + fft[0]);
mUiHandler.sendMessage(
mUiHandler.obtainMessage(VisualizerTest.MSG_DISPLAY_FFT_VAL,
dataToMinMaxCenter(fft, fft.length)));
}
}
}
}