字节数组到短数组并在java中再次返回

Posted

技术标签:

【中文标题】字节数组到短数组并在java中再次返回【英文标题】:byte array to short array and back again in java 【发布时间】:2011-08-03 07:00:30 【问题描述】:

我在获取存储在字节数组中的音频数据、将其转换为大端短数组、对其进行编码、然后将其更改回字节数组时遇到了一些问题。这就是我所拥有的。原始音频数据存储在 audioBytes2 中。我使用相同的格式进行解码,但在 cos 函数上加减号。不幸的是,更改字节和短数据类型是不可协商的。

    short[] audioData = null;
    int nlengthInSamples = audioBytes2.length / 2;
    audioData = new short[nlengthInSamples];

    for (int i = 0; i < nlengthInSamples; i++) 
       short MSB = (short) audioBytes2[2*i+1];
       short LSB = (short) audioBytes2[2*i];
       audioData[i] = (short) (MSB << 8 | (255 & LSB));
    

    int i = 0;
    while (i < audioData.length) 
        audioData[i] = (short)(audioData[i] + (short)5*Math.cos(2*Math.PI*i/(((Number)EncodeBox.getValue()).intValue())));
        i++;
    

    short x = 0;
    i = 0;
    while (i < audioData.length) 
        x = audioData[i];
        audioBytes2[2*i+1] = (byte)(x >>> 0);
        audioBytes2[2*i] = (byte)(x >>> 8);
        i++;
    

我已经尽我所能来完成这项工作,但我最接近的方法是让它在所有其他编码/解码中工作,我不知道为什么。感谢您的帮助。

【问题讨论】:

是大端还是小端?我认为您需要java.nio.ByteBuffer 来处理此转换。 how to convert short array to byte array的可能重复 【参考方案1】:

我也建议你试试 ByteBuffer。

byte[] bytes = ;
short[] shorts = new short[bytes.length/2];
// to turn bytes to shorts as either big endian or little endian. 
ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);

// to turn shorts back to bytes.
byte[] bytes2 = new byte[shortsA.length * 2];
ByteBuffer.wrap(bytes2).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(shortsA);

【讨论】:

short[] audioData = ByteBuffer.wrap(audioBytes2).order(ByteOrder.BIG_ENDIAN).asShortBuffer().array();引发 UnsupportedOperationException。 @Aaron - 是的,但是 what 抛出了那个异常? (提示:ShortBuffer 充当底层ByteBuffer视图,其get() 方法应该完全符合您的要求)。 @kdgregory,直到您提出修复建议。我忘记了 array() 仅在底层存储是 short[] 或类似的原始数组以匹配 XxxxxBuffer 时才有效。 这只是将字节直接转换为短裤还是像我需要的那样将两个字节组合成一个短裤? 如您所见,它创建的shorts 是字节数的一半,而shorts 的字节数是shorts 的两倍。如果它没有进行您需要的转换,那么 ByteOrder 将毫无意义。因为只是将 byte 转换为 short 并再次返回不需要 ByteOrder。如果您有疑问,我建议您尝试一下,看看它是否适合您的需要。【参考方案2】:
public short bytesToShort(byte[] bytes) 
     return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();

public byte[] shortToBytes(short value) 
    return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(value).array();

【讨论】:

它不会将短 array 转换为字节数组。【参考方案3】:

一些 ByteBuffers 怎么样?

byte[] payload = new byte[]0x7F,0x1B,0x10,0x11;
ByteBuffer bb = ByteBuffer.wrap(payload).order(ByteOrder.BIG_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
while(sb.hasRemaining())
  System.out.println(sb.get());

【讨论】:

【参考方案4】:
byte[2] bytes;

int r = bytes[1] & 0xFF;
r = (r << 8) | (bytes[0] & 0xFF);

short s = (short)r;

【讨论】:

【参考方案5】:

您的代码正在做 little-endian shorts,而不是大。您已经交换了 MSB 和 LSB 的索引。

由于您使用的是 big-endian 短裤,因此您可以在另一端使用包装在 ByteArrayInputStream(和 DataOutputStream/ByteArrayOutputStream)周围的 DataInputStream,而不是自己进行解码。

如果您让其他所有解码都正常工作,我猜您的字节数为奇数,或者其他地方出现了一个错误,导致您的错误在其他所有通道中都得到修复。

最后,我将使用 i+=2 遍历数组并使用 MSB= arr[i] 和 LSB=arr[i+1] 而不是乘以 2,但这只是我。

【讨论】:

我实际上正在使用与使用 audioInputStream 重新转换后类似的东西。【参考方案6】:

看起来您在读入和写回字节之间交换字节顺序(不确定这是否是故意的)。

【讨论】:

以上是关于字节数组到短数组并在java中再次返回的主要内容,如果未能解决你的问题,请参考以下文章

将 char 数组转换为字节数组并再次返回

Java将字节数组转换为十六进制字节数组[重复]

java _io_图片到内存(字节数组),字节数组到文件,练习文件流和字节数组流

使用 SharedPreferences 保存字节数组

Java:如何“修剪”字节数组?

从 Java AWS lambda API 响应中的字节数组返回图像