1f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent/* 2f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * Copyright (C) 2010 The Android Open Source Project 3f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * 4f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 5f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * you may not use this file except in compliance with the License. 6f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * You may obtain a copy of the License at 7f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * 8f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * http://www.apache.org/licenses/LICENSE-2.0 9f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * 10f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * Unless required by applicable law or agreed to in writing, software 11f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 12f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * See the License for the specific language governing permissions and 14f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent * limitations under the License. 15f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent */ 16f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 17f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurentpackage com.android.musicvis; 18f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 19f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurentimport android.util.Log; 2018d8fa67c3efc037ddb0be266dd38c5cf35a22c7Eric Laurentimport android.media.audiofx.Visualizer; 21f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 22f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurentimport java.util.Arrays; 23f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 24f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurentpublic class AudioCapture { 25f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 26f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent private byte [] mRawVizData; 27f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent private int [] mFormattedVizData; 28e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent private byte [] mRawNullData = new byte[0]; 29e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent private int [] mFormattedNullData = new int[0]; 30e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent 31f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent private Visualizer mVisualizer; 32f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent private int mType; 33f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 34e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent private static long MAX_IDLE_TIME_MS = 3000; 35e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent private long mLastValidCaptureTimeMs; 36e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent 37f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public static final int TYPE_PCM = 0; 38f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public static final int TYPE_FFT = 1; 39f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 40e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent 41f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public AudioCapture(int type, int size) { 42f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mType = type; 43f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent int[] range = new int[2]; 44f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 45f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent range = Visualizer.getCaptureSizeRange(); 46f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 47f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (size < range[0]) { 48f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent size = range[0]; 49f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 50f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (size > range[1]) { 51f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent size = range[1]; 52f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 53f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 54f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mRawVizData = new byte[size]; 55f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mFormattedVizData = new int[size]; 56f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 57f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer = null; 58f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent try { 59f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer = new Visualizer(0); 60f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mVisualizer != null) { 61f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mVisualizer.getEnabled()) { 62f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer.setEnabled(false); 63f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 64f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer.setCaptureSize(mRawVizData.length); 65f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 66f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } catch (UnsupportedOperationException e) { 67f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Log.e("AudioCapture", "Visualizer cstor UnsupportedOperationException"); 68f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } catch (IllegalStateException e) { 69f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Log.e("AudioCapture", "Visualizer cstor IllegalStateException"); 70f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } catch (RuntimeException e) { 71f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Log.e("AudioCapture", "Visualizer cstor RuntimeException"); 72f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 73f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 74f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 75f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public void start() { 76f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mVisualizer != null) { 77f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent try { 78f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (!mVisualizer.getEnabled()) { 79f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer.setEnabled(true); 80e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent mLastValidCaptureTimeMs = System.currentTimeMillis(); 81f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 82f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } catch (IllegalStateException e) { 83f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Log.e("AudioCapture", "start() IllegalStateException"); 84f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 85f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 86f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 87f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 88f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public void stop() { 89f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mVisualizer != null) { 90f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent try { 91f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mVisualizer.getEnabled()) { 92f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer.setEnabled(false); 93f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 94f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } catch (IllegalStateException e) { 95f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Log.e("AudioCapture", "stop() IllegalStateException"); 96f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 97f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 98f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 99f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 100f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public void release() { 101f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mVisualizer != null) { 102f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer.release(); 103f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVisualizer = null; 104f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 105f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 106f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 107f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public byte[] getRawData() { 108e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent if (captureData()) { 109e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent return mRawVizData; 110e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } else { 111e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent return mRawNullData; 112e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } 113f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 114f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 115f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent public int[] getFormattedData(int num, int den) { 116e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent if (captureData()) { 117e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent if (mType == TYPE_PCM) { 118e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent for (int i = 0; i < mFormattedVizData.length; i++) { 119e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent // convert from unsigned 8 bit to signed 16 bit 120e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent int tmp = ((int)mRawVizData[i] & 0xFF) - 128; 121e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent // apply scaling factor 122e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent mFormattedVizData[i] = (tmp * num) / den; 123e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } 124e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } else { 125e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent for (int i = 0; i < mFormattedVizData.length; i++) { 126e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent // apply scaling factor 127e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent mFormattedVizData[i] = ((int)mRawVizData[i] * num) / den; 128e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } 129f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 130e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent return mFormattedVizData; 131f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } else { 132e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent return mFormattedNullData; 133f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 134f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 135f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 136e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent private boolean captureData() { 137f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent int status = Visualizer.ERROR; 138e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent boolean result = true; 139f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent try { 140f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mVisualizer != null) { 141f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mType == TYPE_PCM) { 142f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent status = mVisualizer.getWaveForm(mRawVizData); 143f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } else { 144f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent status = mVisualizer.getFft(mRawVizData); 145f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 146f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 147f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } catch (IllegalStateException e) { 148f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Log.e("AudioCapture", "captureData() IllegalStateException: "+this); 149f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } finally { 150f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (status != Visualizer.SUCCESS) { 151f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Log.e("AudioCapture", "captureData() : "+this+" error: "+ status); 152e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent result = false; 153e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } else { 154e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent // return idle state indication if silence lasts more than MAX_IDLE_TIME_MS 155e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent byte nullValue = 0; 156e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent int i; 157f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mType == TYPE_PCM) { 158e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent nullValue = (byte)0x80; 159e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } 160e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent for (i = 0; i < mRawVizData.length; i++) { 161e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent if (mRawVizData[i] != nullValue) break; 162e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } 163e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent if (i == mRawVizData.length) { 164e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent if ((System.currentTimeMillis() - mLastValidCaptureTimeMs) > 165e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent MAX_IDLE_TIME_MS) { 166e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent result = false; 167e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent } 168f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } else { 169e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent mLastValidCaptureTimeMs = System.currentTimeMillis(); 170f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 171f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 172f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 173e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent return result; 174f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 175f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent} 176