梅明子 2019-08-21 17:58 采纳率: 100%
浏览 502
已采纳

求助 Android 监听音频波形数据方法返回值的问题

1,我设置的采样是:

visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1])

2,因此从回调方法中返回的byte数据长度是1024个字节

@Override
    public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {
        //采集波形数据

    }

3,而我的项目需求中要绘制的跳动频谱却只有两条,我该从长度为1024的数组中取出哪两个数据来去绘制跳动的频谱呢?下面代码中的方法是我尝试解决的回调函数,其中data就是监听方法中返回的byte数组,只可惜这种方式明显感觉跳动的频率对不上音乐播放的节奏。有大神指点一下吗?万分感谢!

public void onCaptureChanged(byte[] data, boolean isDataVailed, boolean isReverse) {
        this.isReverse = isReverse;

        if (data != null) {
            int leftCentreIndex = data.length / 4 - 1;
            int rightCentreIndex = data.length * 3 / 4 - 1;

            // 给256临近的数据设置权重,并且进行累加
            mData[0] = (int) (data[leftCentreIndex] * 0.4f + data[leftCentreIndex + 1] * 0.3f + data[leftCentreIndex - 1] * 0.3f);
            mData[1] = (int) (data[rightCentreIndex] * 0.4f + data[rightCentreIndex + 1] * 0.3f + data[rightCentreIndex - 1] * 0.3f);
        } else {
            Arrays.fill(this.mData, 0);
        }
        postInvalidate();
    }
  • 写回答

2条回答 默认 最新

  • 梅明子 2019-09-06 17:57
    关注

    结了吧,勉强还能看得过去,主要方法如下:

    public void onCaptureChanged(byte[] data, boolean isDataVailed, boolean isReverse) {
            this.isReverse = isReverse;
    
            if (data == null || !isDataVailed
                    || !EqualizerPreference.getInstance().isShowVisualizer()
                    || !EqualizerDataHelper.get().getAudioEffectEnabled()
                    || !EqualizerHandler.getInstance().isMusicActive()) {
                if (mData == null) {
                    mData = new int[mCylinderNum];
                } else {
                    Arrays.fill(this.mData, 0);
                }
                // 用于减少绘制默认背景的次数
                if (mDefaultDrawCount <= 3) {
                    mDefaultDrawCount++;
                    postInvalidate();
                }
                return;
            }
            if (L.isDebug) {
                L.e(TAG, "--> onCaptureChanged");
            }
            mDefaultDrawCount = 0;
    
            Complex[] complexList = new Complex[mCylinderNum];
            for (int i = 0; i < mCylinderNum; i++) {
                complexList[i] = new Complex(data[i]);
            }
    
            fft(complexList, mCylinderNum);
    
            if (this.mData == null) {
                this.mData = new int[mCylinderNum];
            }
            int[] model = new int[mCylinderNum];
            float x = mHeight / 255F;
            int max = (int) (mHeight * 0.8);
            for (int i = 0; i < mCylinderNum; i++) {
                // 与上一次数据平分, 减小变化幅度
                model[i] = (int) (Math.min(complexList[i].getIntValue() * x, max) / 2f + this.mData[i] / 2f);
            }
            this.mData = model;
            postInvalidate();
        }
    
        /**
         * 快速傅里叶变换算法(FFT)
         */
        public static void fft(Complex[] xin, final int N) {
            int f, m, N2, nm, i, k, j, L;// L:运算级数
            float p;
            int e2, B, ip;
            Complex w = new Complex();
            Complex t = new Complex();
            N2 = N / 2;// 每一级中蝶形的个数,同时也代表m位二进制数最高位的十进制权值
            f = N;// f是为了求流程的级数而设立的
            for (m = 1; (f = f / 2) != 1; m++)
                ; // 得到流程图的共几级
            nm = N - 2;
            j = N2;
            /****** 倒序运算(雷德算法)******/
            for (i = 1; i <= nm; i++) {
                if (i < j) {
                    // 防止重复交换
                    t = xin[j];
                    xin[j] = xin[i];
                    xin[i] = t;
                }
                k = N2;
                while (j >= k) {
                    j = j - k;
                    k = k / 2;
                }
                j = j + k;
            }
            /****** 蝶形图计算部分 ******/
            for (L = 1; L <= m; L++) {
                // 从第1级到第m级
                e2 = (int) Math.pow(2, L);
                B = e2 / 2;
                for (j = 0; j < B; j++) {
                    // j从0到2^(L-1)-1
                    p = 2 * PI / e2;
                    w.real = Math.cos(p * j);
                    w.image = Math.sin(p * j) * -1;
                    for (i = j; i < N; i = i + e2) {
                        // 计算具有相同系数的数据
                        ip = i + B; // 对应蝶形的数据间隔为2^(L-1)
                        t = xin[ip].cc(w);
                        xin[ip] = xin[i].cut(t);
                        xin[i] = xin[i].sum(t);
                    }
                }
            }
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条