【问题标题】:Java - Convert byte[] to double[] and vice versaJava - 将 byte[] 转换为 double[] ,反之亦然
【发布时间】:2011-08-31 16:31:50
【问题描述】:

我正在做一些涉及读取音频数据的事情。我需要将音频数据 byte[] 转换为 double[](反之亦然)。 我需要转换以使信号通过低通滤波器。

为了将表单字节转换为双精度,我使用以下代码 sn-p:

// where data is the byte array.
ByteBuffer byteBuffer = ByteBuffer.wrap(data);
// make sure that the data is in Little endian order.
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
// every double will represent 2 bytes (16bit audio sample)
// so the double[] is half length of byte[]
double[] doubleData = new double[data.length / 2];
int i = 0;
while (byteBuffer.remaining() > 2) {
    // read shorts (16bits) and cast them to doubles
    short t = byteBuffer.getShort();
    doubleData[i] = t;
    doubleData[i] /= 32768.0;
    i++;
}

我不知道这是否是最好的方法,尤其是因为它给出了“Java 堆空间不足异常”以及大量数据字节。

总结一下:

  1. 有没有更好的方法来进行转换,不消耗堆空间
  2. 如何再次将双精度转换回字节?

任何帮助表示赞赏

谢谢,

萨默·萨米

【问题讨论】:

标签: java double bytearray


【解决方案1】:

真的需要double[]吗?我不是float的忠实粉丝,但它会给你足够多的准确度数字并且尺寸只有一半。

如果您想避免使用堆,请使用直接内存,即不要使用 byte[] 或 double[],而是使用 ByteBuffer、ShortBuffer 和 FloatBuffer 作为直接内存。

顺便说一句:设置字节的字节顺序没有任何作用。

ByteBuffer bb = // use direct memory if possible.
ShortBuffer sb = bb.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
FloatBuffer fb = ByteBuffer.allocateDirect(sb.remaining() * 4)
                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
while(sb.remaining()>0)
    fb.put(sb.get() / 32768.0f);

【讨论】:

  • @Peter 小问题,为什么将 FloatBuffer 分配给 (sb.remaining() * 4) ?为什么不只是“sb”的大小?
  • sb.reemiaining() 是数字短值,每个浮点数使用 4 个字节。
【解决方案2】:

查看HugeCollections

Huge 集合库旨在有效地支持对内存中数据的大型集合,而不会产生 GC 影响。它使用堆更少的内存和生成的代码来提高效率。

我知道这不是一个完整的答案(您要求任何帮助),但是对于在 java 中处理大量数据,您会在 vanillajava 博客上找到很多很棒的食谱。 p>

【讨论】:

    【解决方案3】:

    只是关于堆空间的一个随机想法:您可以稍后在处理数组时创建/= 32768.0

    编辑:代码中的错字

    short[] shortData = new short[data.length / 2];
    int i = 0;
    while (byteBuffer.remaining() > 2) {
        // read shorts (16bits) and cast them to doubles
        short t = byteBuffer.getShort();
        shortData[i] = t;
        i++;
    }
    

    【讨论】:

    • 我以后怎么做?! ...我需要保留一个大小相同的双精度数组,堆问题来自该行:double[] doubleData = new double[data.length / 2];
    • 抱歉,我在代码中编辑了一个错字。不,您不需要保留相同大小的双精度数组。稍后,当你处理你的短数组时,你会一个一个地把它翻倍。无论如何,Peter Lawrey 的缓冲小费更好。
    【解决方案4】:

    您使用的唯一使用大量堆的东西是“数据”,尤其是“双数据”。因此,如果您正在寻找一种减少堆空间的方法,那么您就找错了地方——您必须找到一种工作方式,而不是同时在内存中拥有所有双打。或者……

    你知道如何扩展 Java 堆大小吗?如果没有,您需要学习 - 默认大小很小 - 如果内存可用(可以这么说),只有 64MB。从命令行,例如,为半场演出添加“-Xmx512m”:

    java -Xmx512m MyApp
    

    【讨论】:

      猜你喜欢
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 2013-07-16
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      • 2015-03-05
      • 2013-08-09
      相关资源
      最近更新 更多