java - android Visualizer getWaveForm(字节[]波形)总是返回-128
问题描述
我正在尝试捕捉我的 android 设备(收音机、youtube ......)中播放的一小部分音乐。
我尝试使用可视化工具getWaveForm
( byte[] waveform
) 方法:
import android.media.MediaPlayer;
import android.media.audiofx.Visualizer;
import android.os.Build;
import android.os.SystemClock;
import android.util.Log;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class GrabAudio {
private final String TAG = "test11";
private byte[] mRawData;
private int[] mFormattedData;
private int mType;
private Visualizer mVisualizer;
private Method mSnoop;
private boolean mUseSnoop = false;
private long silencePeriod;
private Random randomGen = new Random();
private int[] calculatedData;
private Queue<Integer> queue = new LinkedList<Integer>();
private int[] pcmData;
private int size;
public static final int PCM_TYPE = 0;
public static final int FFT_TYPE = 1;
public GrabAudio(int type, int size, int audioSession) {
Log.i("test11", "GrabAudio:(" + type + "," + size + "," + audioSession);
this.size = size;
if (Build.VERSION.SDK_INT < 9)
mUseSnoop = true;
silencePeriod = SystemClock.uptimeMillis();
pcmData = new int[size];
for (int i = 0; i < size; i++)
pcmData[i] = (int) (randomGen.nextFloat() * 60 - 30);
/*for(int i = 0; i < pcmData.length; i++)
queue.offer(pcmData[i]);*/
mFormattedData = new int[size];
calculatedData = new int[size];
if (!mUseSnoop) {
int range[] = new int[2];
range = Visualizer.getCaptureSizeRange();
//Log.v(TAG, Integer.toString(range[0]) + "-" + Integer.toString(range[1]));
mType = type;
if (size < range[0]) {
size = range[0];
}
if (size > range[1]) {
size = range[1];
}
mRawData = new byte[size];
if (type == FFT_TYPE)
size /= 2;
mVisualizer = null;
try {
mVisualizer = new Visualizer(audioSession);
if (mVisualizer != null) {
if (mVisualizer.getEnabled()) {
mVisualizer.setEnabled(false);
}
mVisualizer.setCaptureSize(mRawData.length);
}
} catch (UnsupportedOperationException e) {
Log.v(TAG, "UnsupportedOperationException");
} catch (IllegalStateException e) {
Log.v(TAG, "IllegalStateException");
} catch (RuntimeException e) {
Log.v(TAG, "RuntimeException");
}
}
Log.i("test11", "GrabAudio: arr len:" + this.mRawData.length);
}
public void start() {
Log.i("test11", "start");
if (!mUseSnoop) {
if (mVisualizer != null) {
try {
if (!mVisualizer.getEnabled()) {
mVisualizer.setEnabled(true);
}
} catch (IllegalStateException e) {
Log.e(TAG, "start() IllegalStateException");
}
}
}
}
public void stop() {
Log.i("test11", "stop");
if (!mUseSnoop) {
if (mVisualizer != null) {
try {
if (mVisualizer.getEnabled()) {
mVisualizer.setEnabled(false);
}
} catch (IllegalStateException e) {
Log.v(TAG, "stop() IllegalStateException");
}
}
}
}
public void release() {
Log.i("test11", "release");
if (!mUseSnoop) {
if (mVisualizer != null) {
mVisualizer.release();
mVisualizer = null;
}
}
}
public byte[] getRawData() {
Log.i("test11", "getRawData");
captureData();
return mRawData;
}
public int[] getFormattedData(int num, int den) {
if (num == 0)
num += 1;
if (!mUseSnoop) {
captureData();
if (mType == PCM_TYPE) {
for (int i = 0; i < mFormattedData.length; i++) {
int tmp = ((int) mRawData[i] & 0xFF) - 128;
mFormattedData[i] = (tmp * num) / den;
}
} else {
for (int i = 0; i < mFormattedData.length; i++) {
mFormattedData[i] = ((int) mRawData[i] * num) / den;
}
}
} else {
short[] temp = new short[calculatedData.length];
if (snoop(temp, 0) != 1)
for (int i = 0; i < temp.length; i++) {
calculatedData[i] = ((int) temp[i] * num) / 100;
mFormattedData = calculatedData;
}
else {
Arrays.fill(calculatedData, 0);
mFormattedData = calculatedData;
}
}
if (mFormattedData[0] == 0 && SystemClock.uptimeMillis() - silencePeriod >= 2000) {
mFormattedData = getFakeData(num, den);
} else if (mFormattedData[0] != 0) {
silencePeriod = SystemClock.uptimeMillis();
}
return mFormattedData;
}
public void captureData() {
Log.i("test11", "captureData");
int status = Visualizer.ERROR;
try {
if (mType == PCM_TYPE) {
status = mVisualizer.getWaveForm(mRawData);
Log.i("test11", "getWaveForm(mRawData)");
} else
status = mVisualizer.getFft(mRawData);
} catch (Exception e) {
} finally {
if (status != Visualizer.SUCCESS) {
Log.i("test11", "status != Visualizer.SUCCESS");
Log.v(TAG, Integer.toString(status));
if (mType == PCM_TYPE)
Arrays.fill(mRawData, (byte) 0x80);
else
Arrays.fill(mRawData, (byte) 0);
}
}
// Log.i("test11","captureData end:\n" + Arrays.toString(mRawData));
}
private static int customParseInt(final String s) {
Log.i("test11", "customParseInt: ");
// Check for a sign.
int num = 0;
int sign = -1;
final int len = s.length();
final char ch = s.charAt(0);
if (ch == '-')
sign = 1;
else
num = '0' - ch;
// Build the number.
int i = 1;
while (i < len)
num = num * 10 + '0' - s.charAt(i++);
return sign * num;
}
private int snoop(short[] outData, int kind) {
Log.i("test11", "in snoop()");
if (mSnoop != null) {
try {
return customParseInt((mSnoop.invoke(MediaPlayer.class, outData, kind)).toString());
} catch (Exception e) {
Log.e(TAG, "Failed to MediaPlayer.snoop()!", e);
return 1;
}
} else {
try {
Class c = MediaPlayer.class;
Method m = c.getMethod("snoop", outData.getClass(), Integer.TYPE);
m.setAccessible(true);
mSnoop = m;
return customParseInt((m.invoke(c, outData, kind)).toString());
} catch (Exception e) {
Log.e(TAG, "Failed to MediaPlayer.snoop()!", e);
return 1;
}
}
}
private int[] getFakeData(int num, int den) {
//fakeData(num, den);
for (int i = 0; i < size; i++)
mFormattedData[i] = 0;
return mFormattedData;
}
private void fakeData(int num, int den) {
int temp = 0;
for (int i = 0; i < mFormattedData.length; i++) {
temp = queue.poll();
mFormattedData[i] = 0;
queue.offer(temp);
}
}
private int random(int a) {
return randomGen.nextInt(a);
}
}
这是主要功能:
GrabAudio gr = new GrabAudio(0, 1024, mp.getAudioSessionId());
gr.start();
byte[] b = gr.getRawData();
gr.release();
Log.i("test11", "b:" + Arrays.toString(b));
这就是我在日志中得到的:
b:[-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128 , -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128.. .
解决方案
好吧,您的代码很多且难以理解,但是实际getRawData()
方法返回mRawData
. 那里面的内容只用在方法中getFormattedData()
。所以我建议你尝试打电话byte[] b = grabAudio.getFormattedData()
。
另请注意,getRawData()
只有mRawData
在出现问题的情况下才会填写:
if (mType == PCM_TYPE)
Arrays.fill(mRawData, (byte) 0x80);
else
Arrays.fill(mRawData, (byte) 0);
0x80
在这种情况下-128
,所以您提供的声音有问题。因此,我建议您查看并找出为什么getRawData()
会出现错误。
另请参阅此处的原始来源,并看看它是如何在那里实现的:
推荐阅读
- mysql - MySQL 实体框架:无法创建索引
- react-native - React Native - 单击时更改其他图标颜色
- javascript - pm2 不使用实验模块标志
- reactjs - CSS对象中的条件
- python - 比较python中相应索引处的键和值
- angular - 错误 500 预览仅在 Postman 上的 Chrome 上未显示
- python - 为 pandas 数据框中的所有列提取显式类型
- javascript - 砌体布局问题
- sonarqube - 缺少 SonarQube 已弃用的规则建议
- python - 我可以使用 Python 为 Influxdb 中的某个点设置特定时间吗?