简体   繁体   English

有符号的16位PCM转换不起作用。 为什么?

[英]Signed 16 bit PCM transformations aren't working. Why?

For the past 2 days I've been trying to manipulate 16 bit PCM data on Android with little success. 在过去的两天里,我一直试图在Android上操纵16位PCM数据,但收效甚微。 I'm currently using WAV recorder to capture audio. 我目前正在使用WAV录音机来捕捉音频。 In the onPeriodicNotification(AudioRecord recorder) method before the buffer is written with the randomAccessWriter I send the buffer to a custom class, to manipulate the samples, and save the samples back into the buffer. onPeriodicNotification(AudioRecord recorder)法在缓冲之前与写入randomAccessWriter我缓冲器发送到一个自定义类,来操纵的样品中,并保存该样品回到缓冲器中。 The method in my custom class is as follows: 我的自定义类中的方法如下:

As the buffer is a byte array I first convert them into shorts, now one short represents a frame (there's only one channel). 由于缓冲区是一个字节数组,我首先将它们转换为短路,现在一个短路代表一个帧(只有一个通道)。 I will be implementing FFT algorithms, once I get past this hurdle, that need the input to be a float array - so I convert each short into a float. 我将实现FFT算法,一旦我越过这个障碍,需要输入为浮点数组 - 所以我将每个短路转换为浮点数。 Now, the randomAccessWriter that writes the data into the WAV file accepts a byte array and is expecting each frame to be 2 bytes. 现在,将数据写入WAV文件的randomAccessWriter接受一个字节数组,并期望每个帧为2个字节。 Therefore I convert each float back into a short and use a ByteBuffer to reconstruct a byte array, which is then returned. 因此,我将每个float转换回short并使用ByteBuffer重建一个字节数组,然后返回该数组。 When I run my recorder app, with the buffer being sent through the above code, everything is fine. 当我运行我的录音机应用程序时,通过上面的代码发送缓冲区,一切都很好。

I try using a simple voice modulation algorithm to test if the recording is modified, the algorithm is placed where the TODO comment is: 我尝试使用简单的语音调制算法来测试录音是否被修改,算法放在TODO评论的位置:

Now if I used the above code on my iPhone the audio samples would be transformed, although the data is natively 32bit floats. 现在如果我在我的iPhone上使用上面的代码,音频样本将被转换,尽管数据本身是32位浮点数。 However, on Android when I re-run the recorder app, with the above code inserted, all that's produced is white noise. 但是,在我重新运行录音机应用程序的Android上,插入上面的代码后,产生的所有内容都是白噪声。 Until I can successfully modify the samples with the above code, I can't proceed with my FFT algorithms. 在我用上面的代码成功修改样本之前,我无法继续使用我的FFT算法。

Why is this occurring? 为什么会这样? I would be grateful if someone with knowledge on the topic could shed light on the topic. 如果有关于该主题的知识的人能够阐明这一主题,我将不胜感激。

SOLVED - By Bjorn Roche 解决 - 由Bjorn Roche

Underlying cause: Recording was giving data in Little Endian whereas Java shorts are in Big Endian; 基本原因:录制正在Little Endian提供数据,而Java短片则在Big Endian; when applying a function using the two different forms, white noise is produced. 当使用两种不同形式应用函数时,会产生白噪声。 The below code shows how to take in a Little Endian byte array, convert to Big Endian float array and back to Little Endian byte array. 下面的代码显示了如何接收Little Endian字节数组,转换为Big Endian浮点数组并返回Little Endian字节数组。 Whilst floats you can do whatever you please, I'll now be using my FFT algorithms: 虽然浮动你可以随心所欲,我现在将使用我的FFT算法:

public byte[] manipulateSamples(byte[] data,
                                int samplingRate,
                                int numFrames,
                                short numChannels) {

    // Convert byte[] to short[] (16 bit) to float[] (32 bit) (End result: Big Endian)
    ShortBuffer sbuf = ByteBuffer.wrap(data).asShortBuffer();
    short[] audioShorts = new short[sbuf.capacity()];
    sbuf.get(audioShorts);

    float[] audioFloats = new float[audioShorts.length];

    for (int i = 0; i < audioShorts.length; i++) {
        audioFloats[i] = ((float)Short.reverseBytes(audioShorts[i])/0x8000);
    }

    // Do your tasks here.

    // Convert float[] to short[] to byte[] (End result: Little Endian)
    audioShorts = new short[audioFloats.length];
    for (int i = 0; i < audioFloats.length; i++) {
        audioShorts[i] = Short.reverseBytes((short) ((audioFloats[i])*0x8000));
    }

    byte byteArray[] = new byte[audioShorts.length * 2];
    ByteBuffer buffer = ByteBuffer.wrap(byteArray);
    sbuf = buffer.asShortBuffer();
    sbuf.put(audioShorts);
    data = buffer.array();

    return data;

}

你的问题是java中的short是bigendian,但如果从WAV文件中获取数据,那么数据就是小端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM