EnergyProbe.java revision 1a5149e5d7f2dddc8b324f7695e69fd89af73c52
1b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent/*
2b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * Copyright (C) 2010 The Android Open Source Project
3b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *
4b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * you may not use this file except in compliance with the License.
6b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * You may obtain a copy of the License at
7b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *
8b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *
10b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * Unless required by applicable law or agreed to in writing, software
11b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * See the License for the specific language governing permissions and
14b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * limitations under the License.
15b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent */
16b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
17b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentpackage com.android.mediaframeworktest.functional;
18b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
19b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentimport android.media.audiofx.Visualizer;
20b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentimport android.util.Log;
21b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
22b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent/**
23b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * The EnergyProbe class provides audio signal energy measurements based on the FFT returned
24b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * by the Visualizer class. The measure is qualitative and not quantitative in that the returned
25b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * value has no unit and is just proportional to the amount of energy present around the
26b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * specified frequency.
27b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent */
28b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
29b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentpublic class EnergyProbe {
30df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    private String TAG = "EnergyProbe";
31df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
32b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    private static int CAPTURE_SIZE = 1024;
33b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    private static int MEASURE_COUNT = 5;
34b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    private static int AVERAGE_COUNT = 3;
35b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
36b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    private Visualizer mVisualizer = null;
37b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    private int mMaxFrequency = 0;
38b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    private int mCapturePeriodMs;
39b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    private byte[] mFft = new byte[CAPTURE_SIZE];
40b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
41b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    public EnergyProbe(int session) {
42b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        try {
43b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mVisualizer = new Visualizer(session);
44b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            if (mVisualizer != null) {
45b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mVisualizer.setCaptureSize(CAPTURE_SIZE);
46b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mMaxFrequency = mVisualizer.getSamplingRate() / 2000;
47b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mCapturePeriodMs = 1000000 / mVisualizer.getMaxCaptureRate();
48b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
49b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        } catch (UnsupportedOperationException e) {
50b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            Log.e(TAG, "Error creating visualizer");
51b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        } catch (IllegalStateException e) {
52df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            Log.e(TAG, "Error configuring visualizer");
53df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
54df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
55df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
56df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    public int capture(int freq) throws InterruptedException {
57df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        int energy = 0;
58df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        int count = 0;
59df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
60df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (freq > mMaxFrequency) {
61df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return 0;
62df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
63df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
64df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mVisualizer != null) {
65df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            try {
66df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                mVisualizer.setEnabled(true);
67df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                for (int i = 0; i < MEASURE_COUNT; i++) {
68df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
69df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                        if (freq == mMaxFrequency) {
70df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                            energy += (int)mFft[0] * (int)mFft[0];
71b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        } else {
72b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            int bin = 2 * (freq * CAPTURE_SIZE / mMaxFrequency / 2);
73b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            if (bin < 2) bin = 2;
74b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            int tmp = 0;
75b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            int j;
76b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            for (j = 0;
77b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                 (j < AVERAGE_COUNT) && ((bin + 2 * j) < CAPTURE_SIZE);
78b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                 j++) {
79b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                tmp += (int)mFft[bin + 2 * j] * (int)mFft[bin + 2 * j] +
80b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                       (int)mFft[bin + 2 * j + 1] * (int)mFft[bin + 2 * j + 1];
81b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            }
82b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            // j is always != 0
83b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                            energy += tmp/j;
84b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        }
85b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        count++;
86b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                    }
87b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                    Thread.sleep(mCapturePeriodMs);
88b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                }
89df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                mVisualizer.setEnabled(false);
90df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            } catch (IllegalStateException e) {
91df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                Log.e(TAG, "Error capturing audio");
92df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            }
93df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
94df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (count == 0) {
95df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return 0;
96df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
97df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return energy/count;
98df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
99df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
100df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    public void release() {
101df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mVisualizer != null) {
102df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            mVisualizer.release();
103b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mVisualizer = null;
104b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
105b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
106b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
107b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent