【问题标题】:How to convert 16-bit PCM audio byte-array to double or float array?如何将 16 位 PCM 音频字节数组转换为双精度或浮点数组?
【发布时间】:2012-05-06 15:36:58
【问题描述】:

我正在尝试对 .3gpp 音频文件执行快速傅立叶变换。该文件包含来自手机麦克风的 44100kHz 的 5 秒小录音。

由于显而易见的原因,我能找到的每个 Java FFT 算法都只需要 double[]、float[] 或 Complex[] 输入,但我正在以字节数组的形式读取音频文件,所以我有点对我从这里去哪里感到困惑。我唯一能找到的是上一个问题的答案:

Android audio FFT to retrieve specific frequency magnitude using audiorecord

但我不确定这是否是正确的程序。有任何见解的人吗?

【问题讨论】:

    标签: java android fft


    【解决方案1】:

    别无选择。您必须运行一个循环并分别转换数组的每个元素。

    我对短裤做同样的事情,我 fft 作为花车:

    public static float[] floatMe(short[] pcms) {
        float[] floaters = new float[pcms.length];
        for (int i = 0; i < pcms.length; i++) {
            floaters[i] = pcms[i];
        }
        return floaters;
    }
    

    基于 cmets 编辑 2012 年 4 月 26 日

    如果你确实有 16 位 PCM,但它是一个字节[],那么你可以这样做:

    public static short[] shortMe(byte[] bytes) {
        short[] out = new short[bytes.length / 2]; // will drop last byte if odd number
        ByteBuffer bb = ByteBuffer.wrap(bytes);
        for (int i = 0; i < out.length; i++) {
            out[i] = bb.getShort();
        }
        return out;
    }
    

    然后

    float[] pcmAsFloats = floatMe(shortMe(bytes));
    

    除非您使用的是一个奇怪且设计糟糕的类,它首先为您提供了字节数组,否则该类的设计者应该将字节打包以与 Java 转换字节的方式一致(一次 2 个)穿短裤。

    【讨论】:

    • 谢谢,我只是对 Java 知道如何解释这些数据感到困惑。也许我已经完全了解它是如何存储错误的(看看我对凯尔回答的评论)。无论如何,任何代码都值得赞赏,如果我不明白的话,我会使用它。
    • 感谢 mwengler 的编辑。但是, pcmAsFloats 不应该是短数组的一半吗? 1 个浮点 = 4 个字节,1 个短 = 2 个字节?
    • 没关系,它当然应该与短数组的长度相同,因为它是相同数量的样本。
    【解决方案2】:
    byte[] yourInitialData;
    double[] yourOutputData = ByteBuffer.wrap(bytes).getDouble()
    

    【讨论】:

    • 这看起来很优雅,但我想让我感到困惑的是这看起来太随意了(当谈到 Java 中的音频时,我是绿色的)。如果 16 位 PCM 以字节为单位存储,它代表了模拟信号随时间变化的功率,那么转换过程不应该知道这种结构吗?我的意思是,getDouble() 怎么知道这是一个音频文件?
    • 查看文档我看到 getDouble() 实际上返回一个双精度,而不是双精度 []。所以这行不通。
    • @Kyle 这个答案是错误的。大错特错,它甚至无法编译。 - getDouble() 返回类型 double 而不是 double[]。这会停止它的编译。 - getDouble() 一次抓取 4 个字节,将它们以 32 位串在一起,并将整个内容解释为 double。由于字节数组未存储为doubles,这将产生乱码结果,并且只有shorts 放入数组中的doubles 数量的1/2 可以从数组中提取。 - 有关使用 ByteBuffer 将 byte[] 转换为 short[] 的方法,请参阅上面的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 2012-04-06
    相关资源
    最近更新 更多