首页 > 解决方案 > 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.. .

标签: javaandroidvisualizer

解决方案


好吧,您的代码很多且难以理解,但是实际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()会出现错误。

另请参阅此处的原始来源,并看看它是如何在那里实现的:

https://github.com/EvanJRichter/AudioVisualizer/blob/master/Visualizer/src/com/evanrichter/visualizer/DrawingPanel.java#L830


推荐阅读