【问题标题】:Java - from short to byte[2] using LITTLE_ENDIANJava - 从短到字节[2] 使用 LITTLE_ENDIAN
【发布时间】:2012-05-11 10:54:19
【问题描述】:

我在尝试将短值转换为字节 [2] 时遇到了一些问题。我正在使用它对一些音频数据缓冲区进行一些转换(将增益应用于缓冲区)。首先我像这样加载音频缓冲区:

mRecorder.read(buffer, 0, buffer.length);

缓冲区在哪里

private byte[] buffer;

然后,我得到了样本(录音是 16 位样本大小),如下所示:

short sample = getShort(buffer[i*2], buffer[i*2+1]);

getShort 是这样定义的:

/* 
 * 
 * Converts a byte[2] to a short, in LITTLE_ENDIAN format
 * 
 */
private short getShort(byte argB1, byte argB2)
{
    return (short)(argB1 | (argB2 << 8));
}

然后我将增益应用于样本:

sample *= rGain;

在此之后,我尝试从相乘的样本中取回字节数组:

byte[] a = getByteFromShort(sample);

但这失败了,因为即使增益为1,声音也有很多噪音。

下面是getByteFromShort方法定义:

    private byte[] getByteFromShort(short x){
//variant 1 - noise
    byte[] a = new byte[2];
    a[0] = (byte)(x & 0xff);
    a[1] = (byte)((x >> 8) & 0xff);

//variant 2 - noise and almost broke my ears - very loud
//      ByteBuffer buffer = ByteBuffer.allocate(2);
//      buffer.putShort(x);
//      buffer.flip();

    return a;
}

所以问题在于将短值转换为字节[2]。当增益为 1.0 时,声音充满了噪音。

以下是完整的增益应用方法:

for (int i=0; i<buffer.length/2; i++)
{ // 16bit sample size                      
    short curSample = getShort(buffer[i*2], buffer[i*2+1]);
if(rGain != 1){
    //apply gain
    curSample *= rGain;
    //convert back from short sample that was "gained" to byte data
    byte[] a = getByteFromShort(curSample);
    //modify buffer to contain the gained sample
    buffer[i*2] = a[0];
    buffer[i*2 + 1] = a[1];
}

   }

请你们看看 getByteFromShort 方法并告诉我哪里错了吗?

谢谢。

【问题讨论】:

    标签: java audio bytearray audio-recording


    【解决方案1】:

    getByteFromShort() 似乎还可以。

    getShort(byte argB1, byte argB2) 是错误的。当 argB1 为负数时,它会产生不正确的结果。

    应该是

    return (short)((argB1 & 0xff) | (argB2 << 8));
    

    【讨论】:

    • 谢谢,这解决了问题。
    【解决方案2】:

    使用以下代码:

    ret[0] = (byte)(x & 0xff);
    ret[1] = (byte)((x >> 8) & 0xff);
    

    【讨论】:

    • 不起作用。我将 byte[2] (-60, 1) 转换为 short = -60,然后按照您的建议返回,从 -60 将产生 byte[2] (-60, -1) 而不是 -60 和 1 作为原始值。
    • 这里是我使用的字节转短方法:return (short)(argB1 | (argB2
    【解决方案3】:

    我会使用 ByteBuffer

    ByteBuffer buffer = ByteBuffer.allocate(8*1024);
    mRecorder.read(buffer.array(), 0, buffer.capacity());
    // using NIO
    mRecorder.read(buffer);
    
    while(buffer.remaining() > 1) {
        short s = bb.getShort(x);
        // do something with s
    }
    

    【讨论】:

      【解决方案4】:

      ByteBuffer 及其在 java.nio 中的同类可以帮助解决这个问题。基本上,您将使用您的数据ByteBuffer.wrap(array) 创建一个由数组支持的 ByteBuffer。然后,您可以使用 ByteBuffer.order() 设置缓冲区的字节顺序,并使用 get/put Int/Short/byte... 等函数来操作底层数组中的数据。

      【讨论】:

      • 谢谢,我会使用 ByteBuffer 和你建议的方法。
      猜你喜欢
      • 2010-10-18
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      • 2014-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多