1/*
2 * Copyright (C) 2010 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
17package com.android.mediaframeworktest.functional;
18
19import android.media.audiofx.Visualizer;
20import android.util.Log;
21
22/**
23 * The EnergyProbe class provides audio signal energy measurements based on the FFT returned
24 * by the Visualizer class. The measure is qualitative and not quantitative in that the returned
25 * value has no unit and is just proportional to the amount of energy present around the
26 * specified frequency.
27 */
28
29public class EnergyProbe {
30    private String TAG = "EnergyProbe";
31
32    private static int CAPTURE_SIZE = 1024;
33    private static int MEASURE_COUNT = 5;
34    private static int AVERAGE_COUNT = 3;
35
36    private Visualizer mVisualizer = null;
37    private int mMaxFrequency = 0;
38    private int mCapturePeriodMs;
39    private byte[] mFft = new byte[CAPTURE_SIZE];
40
41    public EnergyProbe(int session) {
42        try {
43            mVisualizer = new Visualizer(session);
44            if (mVisualizer != null) {
45                mVisualizer.setCaptureSize(CAPTURE_SIZE);
46                mMaxFrequency = mVisualizer.getSamplingRate() / 2000;
47                mCapturePeriodMs = 1000000 / mVisualizer.getMaxCaptureRate();
48            }
49        } catch (UnsupportedOperationException e) {
50            Log.e(TAG, "Error creating visualizer");
51        } catch (IllegalStateException e) {
52            Log.e(TAG, "Error configuring visualizer");
53        }
54    }
55
56    public int capture(int freq) throws InterruptedException {
57        int energy = 0;
58        int count = 0;
59
60        if (freq > mMaxFrequency) {
61            return 0;
62        }
63
64        if (mVisualizer != null) {
65            try {
66                mVisualizer.setEnabled(true);
67                for (int i = 0; i < MEASURE_COUNT; i++) {
68                    if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
69                        if (freq == mMaxFrequency) {
70                            energy += (int)mFft[0] * (int)mFft[0];
71                        } else {
72                            int bin = 2 * (freq * CAPTURE_SIZE / mMaxFrequency / 2);
73                            if (bin < 2) bin = 2;
74                            int tmp = 0;
75                            int j;
76                            for (j = 0;
77                                 (j < AVERAGE_COUNT) && ((bin + 2 * j) < CAPTURE_SIZE);
78                                 j++) {
79                                tmp += (int)mFft[bin + 2 * j] * (int)mFft[bin + 2 * j] +
80                                       (int)mFft[bin + 2 * j + 1] * (int)mFft[bin + 2 * j + 1];
81                            }
82                            // j is always != 0
83                            energy += tmp/j;
84                        }
85                        count++;
86                    }
87                    Thread.sleep(mCapturePeriodMs);
88                }
89                mVisualizer.setEnabled(false);
90            } catch (IllegalStateException e) {
91                Log.e(TAG, "Error capturing audio");
92            }
93        }
94        if (count == 0) {
95            return 0;
96        }
97        return energy/count;
98    }
99
100    public void release() {
101        if (mVisualizer != null) {
102            mVisualizer.release();
103            mVisualizer = null;
104        }
105    }
106}
107