• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.effectstest;
18 
19 import android.media.audiofx.Visualizer;
20 import android.os.Handler;
21 import android.os.Message;
22 import android.util.Log;
23 
24 // This class only has `final' members, thus any thread-safety concerns
25 // can only come from the Visualizer effect class.
26 class VisualizerInstanceSync implements VisualizerInstance {
27 
28     private static final String TAG = "VisualizerInstance";
29 
30     private final Handler mUiHandler;
31     private final Visualizer mVisualizer;
32     private final VisualizerTestHandler mVisualizerTestHandler;
33     private final VisualizerListener mVisualizerListener;
34 
VisualizerInstanceSync(int session, Handler uiHandler)35     VisualizerInstanceSync(int session, Handler uiHandler) {
36         mUiHandler = uiHandler;
37         try {
38             mVisualizer = new Visualizer(session);
39         } catch (UnsupportedOperationException e) {
40             Log.e(TAG, "Visualizer library not loaded");
41             throw new RuntimeException("Cannot initialize effect");
42         } catch (RuntimeException e) {
43             throw e;
44         }
45         mVisualizerTestHandler = new VisualizerTestHandler();
46         mVisualizerListener = new VisualizerListener();
47     }
48 
49     // Not a "deep" copy, only copies the references.
VisualizerInstanceSync(VisualizerInstanceSync other)50     VisualizerInstanceSync(VisualizerInstanceSync other) {
51         mUiHandler = other.mUiHandler;
52         mVisualizer = other.mVisualizer;
53         mVisualizerTestHandler = other.mVisualizerTestHandler;
54         mVisualizerListener = other.mVisualizerListener;
55     }
56 
57     @Override
enableDataCaptureListener(boolean enable)58     public void enableDataCaptureListener(boolean enable) {
59         mVisualizer.setDataCaptureListener(enable ? mVisualizerListener : null,
60                 10000, enable, enable);
61     }
62 
63     @Override
getEnabled()64     public boolean getEnabled() {
65         return mVisualizer.getEnabled();
66     }
67 
68     @Override
release()69     public void release() {
70         mVisualizer.release();
71         Log.d(TAG, "Visualizer released");
72     }
73 
74     @Override
setEnabled(boolean enabled)75     public void setEnabled(boolean enabled) {
76         mVisualizer.setEnabled(enabled);
77     }
78 
79     @Override
startStopCapture(boolean start)80     public void startStopCapture(boolean start) {
81         mVisualizerTestHandler.sendMessage(mVisualizerTestHandler.obtainMessage(
82                         start ? MSG_START_CAPTURE : MSG_STOP_CAPTURE));
83     }
84 
85     private static final int MSG_START_CAPTURE = 0;
86     private static final int MSG_STOP_CAPTURE = 1;
87     private static final int MSG_NEW_CAPTURE = 2;
88     private static final int CAPTURE_PERIOD_MS = 100;
89 
dataToMinMaxCenter(byte[] data, int len)90     private static int[] dataToMinMaxCenter(byte[] data, int len) {
91         int[] minMaxCenter = new int[3];
92         minMaxCenter[0] = data[0];
93         minMaxCenter[1] = data[len - 1];
94         minMaxCenter[2] = data[len / 2];
95         return minMaxCenter;
96     }
97 
98     private class VisualizerTestHandler extends Handler {
99         private final int mCaptureSize;
100         private boolean mActive = false;
101 
VisualizerTestHandler()102         VisualizerTestHandler() {
103             mCaptureSize = mVisualizer.getCaptureSize();
104         }
105 
106         @Override
handleMessage(Message msg)107         public void handleMessage(Message msg) {
108             switch (msg.what) {
109                 case MSG_START_CAPTURE:
110                     if (!mActive) {
111                         Log.d(TAG, "Start capture");
112                         mActive = true;
113                         sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE), CAPTURE_PERIOD_MS);
114                     }
115                     break;
116                 case MSG_STOP_CAPTURE:
117                     if (mActive) {
118                         Log.d(TAG, "Stop capture");
119                         mActive = false;
120                     }
121                     break;
122                 case MSG_NEW_CAPTURE:
123                     if (mActive) {
124                         if (mCaptureSize > 0) {
125                             byte[] data = new byte[mCaptureSize];
126                             if (mVisualizer.getWaveForm(data) == Visualizer.SUCCESS) {
127                                 int len = data.length < mCaptureSize ? data.length : mCaptureSize;
128                                 mUiHandler.sendMessage(
129                                         mUiHandler.obtainMessage(
130                                                 VisualizerTest.MSG_DISPLAY_WAVEFORM_VAL,
131                                                 dataToMinMaxCenter(data, len)));
132                             }
133                             if (mVisualizer.getFft(data) == Visualizer.SUCCESS) {
134                                 int len = data.length < mCaptureSize ? data.length : mCaptureSize;
135                                 mUiHandler.sendMessage(
136                                         mUiHandler.obtainMessage(VisualizerTest.MSG_DISPLAY_FFT_VAL,
137                                                 dataToMinMaxCenter(data, len)));
138                             }
139                         }
140                         sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE), CAPTURE_PERIOD_MS);
141                     }
142                     break;
143             }
144         }
145     }
146 
147     private class VisualizerListener implements Visualizer.OnDataCaptureListener {
148         @Override
149         public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform,
150                 int samplingRate) {
151             if (visualizer == mVisualizer && waveform.length > 0) {
152                 Log.d(TAG, "onWaveFormDataCapture(): " + waveform[0]
153                         + " smp rate: " + samplingRate / 1000);
154                 mUiHandler.sendMessage(
155                         mUiHandler.obtainMessage(VisualizerTest.MSG_DISPLAY_WAVEFORM_VAL,
156                                 dataToMinMaxCenter(waveform, waveform.length)));
157             }
158         }
159 
160         @Override
161         public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
162             if (visualizer == mVisualizer && fft.length > 0) {
163                 Log.d(TAG, "onFftDataCapture(): " + fft[0]);
164                 mUiHandler.sendMessage(
165                         mUiHandler.obtainMessage(VisualizerTest.MSG_DISPLAY_FFT_VAL,
166                                 dataToMinMaxCenter(fft, fft.length)));
167             }
168         }
169     }
170 }
171