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 17 package com.android.musicvis; 18 19 import android.util.Log; 20 import android.media.audiofx.Visualizer; 21 22 import java.util.Arrays; 23 24 public class AudioCapture { 25 26 private byte [] mRawVizData; 27 private int [] mFormattedVizData; 28 private byte [] mRawNullData = new byte[0]; 29 private int [] mFormattedNullData = new int[0]; 30 31 private Visualizer mVisualizer; 32 private int mType; 33 34 private static long MAX_IDLE_TIME_MS = 3000; 35 private long mLastValidCaptureTimeMs; 36 37 public static final int TYPE_PCM = 0; 38 public static final int TYPE_FFT = 1; 39 40 41 public AudioCapture(int type, int size) { 42 mType = type; 43 int[] range = new int[2]; 44 45 range = Visualizer.getCaptureSizeRange(); 46 47 if (size < range[0]) { 48 size = range[0]; 49 } 50 if (size > range[1]) { 51 size = range[1]; 52 } 53 54 mRawVizData = new byte[size]; 55 mFormattedVizData = new int[size]; 56 57 mVisualizer = null; 58 try { 59 mVisualizer = new Visualizer(0); 60 if (mVisualizer != null) { 61 if (mVisualizer.getEnabled()) { 62 mVisualizer.setEnabled(false); 63 } 64 mVisualizer.setCaptureSize(mRawVizData.length); 65 } 66 } catch (UnsupportedOperationException e) { 67 Log.e("AudioCapture", "Visualizer cstor UnsupportedOperationException"); 68 } catch (IllegalStateException e) { 69 Log.e("AudioCapture", "Visualizer cstor IllegalStateException"); 70 } catch (RuntimeException e) { 71 Log.e("AudioCapture", "Visualizer cstor RuntimeException"); 72 } 73 } 74 75 public void start() { 76 if (mVisualizer != null) { 77 try { 78 if (!mVisualizer.getEnabled()) { 79 mVisualizer.setEnabled(true); 80 mLastValidCaptureTimeMs = System.currentTimeMillis(); 81 } 82 } catch (IllegalStateException e) { 83 Log.e("AudioCapture", "start() IllegalStateException"); 84 } 85 } 86 } 87 88 public void stop() { 89 if (mVisualizer != null) { 90 try { 91 if (mVisualizer.getEnabled()) { 92 mVisualizer.setEnabled(false); 93 } 94 } catch (IllegalStateException e) { 95 Log.e("AudioCapture", "stop() IllegalStateException"); 96 } 97 } 98 } 99 100 public void release() { 101 if (mVisualizer != null) { 102 mVisualizer.release(); 103 mVisualizer = null; 104 } 105 } 106 107 public byte[] getRawData() { 108 if (captureData()) { 109 return mRawVizData; 110 } else { 111 return mRawNullData; 112 } 113 } 114 115 public int[] getFormattedData(int num, int den) { 116 if (captureData()) { 117 if (mType == TYPE_PCM) { 118 for (int i = 0; i < mFormattedVizData.length; i++) { 119 // convert from unsigned 8 bit to signed 16 bit 120 int tmp = ((int)mRawVizData[i] & 0xFF) - 128; 121 // apply scaling factor 122 mFormattedVizData[i] = (tmp * num) / den; 123 } 124 } else { 125 for (int i = 0; i < mFormattedVizData.length; i++) { 126 // apply scaling factor 127 mFormattedVizData[i] = ((int)mRawVizData[i] * num) / den; 128 } 129 } 130 return mFormattedVizData; 131 } else { 132 return mFormattedNullData; 133 } 134 } 135 136 private boolean captureData() { 137 int status = Visualizer.ERROR; 138 boolean result = true; 139 try { 140 if (mVisualizer != null) { 141 if (mType == TYPE_PCM) { 142 status = mVisualizer.getWaveForm(mRawVizData); 143 } else { 144 status = mVisualizer.getFft(mRawVizData); 145 } 146 } 147 } catch (IllegalStateException e) { 148 Log.e("AudioCapture", "captureData() IllegalStateException: "+this); 149 } finally { 150 if (status != Visualizer.SUCCESS) { 151 Log.e("AudioCapture", "captureData() : "+this+" error: "+ status); 152 result = false; 153 } else { 154 // return idle state indication if silence lasts more than MAX_IDLE_TIME_MS 155 byte nullValue = 0; 156 int i; 157 if (mType == TYPE_PCM) { 158 nullValue = (byte)0x80; 159 } 160 for (i = 0; i < mRawVizData.length; i++) { 161 if (mRawVizData[i] != nullValue) break; 162 } 163 if (i == mRawVizData.length) { 164 if ((System.currentTimeMillis() - mLastValidCaptureTimeMs) > 165 MAX_IDLE_TIME_MS) { 166 result = false; 167 } 168 } else { 169 mLastValidCaptureTimeMs = System.currentTimeMillis(); 170 } 171 } 172 } 173 return result; 174 } 175 } 176