2

我实现了以下算法将 PCM 16 位音频数据转换为 8 位:

if(encoding == AudioFormat.ENCODING_PCM_8BIT){
    int len = data.length;          
    data1 = new byte[len/2];
    int tempint;

    for (int k = 0, i=1; i < len; i+=2, k++) {
        tempint = ((int)data[i]) ^ 0x00000080; 
        data1[k] = (byte)tempint;
    }
    data=null;
}

哪里data is byte[]。运行此代码后,输出contains a lot of noise并建议我在这里做错了。What should I do besides dropping the lower byte?

[编辑]:修改代码:

if(encoding == AudioFormat.ENCODING_PCM_8BIT){

            int len = data.length;          
            data1 = new byte[len/2];
            for (int i = 0; i < len/2; i++) {                   
                    data1[i] = data[i*2+1];     
            }

  }

the input/output looks like:

 Original data(counter:0) = 4
    Original data(counter:1) = -1
    Original data(counter:2) = 75
    Original data(counter:3) = -1
    Original data(counter:4) = 16
    Original data(counter:5) = -1
    Original data(counter:6) = 44
    Original data(counter:7) = -1
    Original data(counter:8) = 7
    Original data(counter:9) = -1
    Original data(counter:10) = 22
    Original data(counter:11) = -1
    Original data(counter:12) = 22
    Original data(counter:13) = -1
    Original data(counter:14) = 12
    Original data(counter:15) = -1

Output data:(counter:0) = -1
Output data:(counter:1) = -1
Output data:(counter:2) = -1
Output data:(counter:3) = -1
Output data:(counter:4) = -1
Output data:(counter:5) = -1
Output data:(counter:6) = -1
Output data:(counter:7) = -1
Output data:(counter:8) = -1
Output data:(counter:9) = -1
Output data:(counter:10) = -1
Output data:(counter:11) = -1
Output data:(counter:12) = -1
Output data:(counter:13) = -1
Output data:(counter:14) = -1
Output data:(counter:15) = -1

不管我丢掉第一个字节还是第二个字节,噪音仍然存在。在这里我删除了第一个字节(而不是第二个)

4

4 回答 4

5

以下算法大大减少了噪声量,但不能完全消除它:

if(encoding == AudioFormat.ENCODING_PCM_8BIT){  
            ShortBuffer intBuf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
            short[] samples16Bit = new short[intBuf.remaining()];
            intBuf.get(samples16Bit);
            data1 = new byte[samples16Bit.length];
            for (int i = 0; i < samples16Bit.length; i++) {
                data1[i] = (byte)((samples16Bit[i] / 256)+128);
            }
        }
于 2013-07-02T12:22:54.153 回答
3

您遇到的噪音仅仅是由您将音频转换为的位范围引起的。16Bit 信号的本底噪声为 -96dB,而 8Bit 信号的本底噪声为 -48dB。就这些数字而言,这可能看起来并不多,但这是一个巨大的差异。下采样算法几乎总是采用某种抖动来减少与转换相关的噪声量。您可以通过以编程方式或使用任何体面的音频程序创建 8 位正弦波并只听结果来轻松展示质量(和噪声级别)的差异。你会发现 8Bit 的质量并不高。用 16Bit 正弦波重复实验进行比较。不是你,是比特范围。

于 2013-06-28T04:06:52.320 回答
0

为什么不只是这个?

int len = data.length;          
data1 = new byte[len/2];
for (int i=0; i < len/2; ++i)
    data1[i] = data[i*2];

我假设你的数据是 bigendian。如果是 LE,这应该有效:

int len = data.length;          
data1 = new byte[len/2];
for (int i=0; i < len/2; ++i)
    data1[i] = data[i*2+1];
于 2013-06-28T00:03:08.563 回答
-2

由于多种原因,您有很多噪音。您首先只填充数组的所有其他值,未填充的值自动为零,这极大地扭曲了波形。其次,您只是选择原始数据的前 8 位,这意味着如果数据点的前 8 位碰巧全为零,则您将丢失有关特定数据点的所有信息,信息可能位于较高位。

一个天真的建议是缩放所有数据点(如果有符号则除以 2^7),以便最高数据点最多为 8 位,您仍然会丢失信息并引入失真,因为您被迫将数据保存为整数和整数除法将强制相同(接近)范围内的值在除法后相等,但这应该会少很多噪音:)

感谢下面的评论,如果您只从原始数据中获取所有其他数据点,您将引入称为Aliasing的失真。

于 2013-06-27T14:22:29.480 回答