1391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent/*
2391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * Copyright (C) 2010 The Android Open Source Project
3391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent *
4391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * you may not use this file except in compliance with the License.
6391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * You may obtain a copy of the License at
7391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent *
8391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent *
10391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * Unless required by applicable law or agreed to in writing, software
11391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * See the License for the specific language governing permissions and
14391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * limitations under the License.
15391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent */
16391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
17391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurentpackage com.android.mediaframeworktest.functional;
18391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
191a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurentimport android.media.audiofx.Visualizer;
20391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurentimport android.util.Log;
21391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
22391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent/**
23391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * The EnergyProbe class provides audio signal energy measurements based on the FFT returned
24391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * by the Visualizer class. The measure is qualitative and not quantitative in that the returned
25391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * value has no unit and is just proportional to the amount of energy present around the
26391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent * specified frequency.
27391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent */
28391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
29391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurentpublic class EnergyProbe {
30391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private String TAG = "EnergyProbe";
31391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
32391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private static int CAPTURE_SIZE = 1024;
33391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private static int MEASURE_COUNT = 5;
34391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private static int AVERAGE_COUNT = 3;
35391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
36391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private Visualizer mVisualizer = null;
37391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private int mMaxFrequency = 0;
38391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private int mCapturePeriodMs;
39391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    private byte[] mFft = new byte[CAPTURE_SIZE];
40391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
41391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    public EnergyProbe(int session) {
42391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        try {
43391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            mVisualizer = new Visualizer(session);
44391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            if (mVisualizer != null) {
45391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                mVisualizer.setCaptureSize(CAPTURE_SIZE);
46391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                mMaxFrequency = mVisualizer.getSamplingRate() / 2000;
47391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                mCapturePeriodMs = 1000000 / mVisualizer.getMaxCaptureRate();
48391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            }
49391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        } catch (UnsupportedOperationException e) {
50391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            Log.e(TAG, "Error creating visualizer");
51391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        } catch (IllegalStateException e) {
52391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            Log.e(TAG, "Error configuring visualizer");
53391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        }
54391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    }
55391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
56391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    public int capture(int freq) throws InterruptedException {
57391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        int energy = 0;
58391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        int count = 0;
59391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
60391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        if (freq > mMaxFrequency) {
61391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            return 0;
62391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        }
63391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
64391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        if (mVisualizer != null) {
65391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            try {
66391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                mVisualizer.setEnabled(true);
67391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                for (int i = 0; i < MEASURE_COUNT; i++) {
68391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                    if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
69391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                        if (freq == mMaxFrequency) {
70391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            energy += (int)mFft[0] * (int)mFft[0];
71391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                        } else {
72391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            int bin = 2 * (freq * CAPTURE_SIZE / mMaxFrequency / 2);
73391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            if (bin < 2) bin = 2;
74391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            int tmp = 0;
75391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            int j;
76391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            for (j = 0;
77391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                                 (j < AVERAGE_COUNT) && ((bin + 2 * j) < CAPTURE_SIZE);
78391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                                 j++) {
79391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                                tmp += (int)mFft[bin + 2 * j] * (int)mFft[bin + 2 * j] +
80391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                                       (int)mFft[bin + 2 * j + 1] * (int)mFft[bin + 2 * j + 1];
81391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            }
82391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            // j is always != 0
83391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                            energy += tmp/j;
84391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                        }
85391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                        count++;
86391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                    }
87391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                    Thread.sleep(mCapturePeriodMs);
88391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                }
89391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                mVisualizer.setEnabled(false);
90391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            } catch (IllegalStateException e) {
91391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent                Log.e(TAG, "Error capturing audio");
92391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            }
93391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        }
94391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        if (count == 0) {
95391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            return 0;
96391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        }
97391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        return energy/count;
98391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    }
99391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent
100391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    public void release() {
101391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        if (mVisualizer != null) {
102391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            mVisualizer.release();
103391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent            mVisualizer = null;
104391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent        }
105391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent    }
106391e2d0d88c1acd87b1503be276cfa4e7ce66c88Eric Laurent}
107