当前位置: 首页 > 知识库问答 >
问题:

将PCM原始字节转换为WAV字节

仲涵亮
2023-03-14

我正在收听现场电话,并能够获得原始的PCM字节。我还可以通过java的音频api来收听这些字节。这些都在一个小程序上工作。

现在,我希望能够将电话呼叫的原始PCM字节转换为WAV字节,以便直接将其写入ServletOutputStream。这将允许浏览器实际监听电话。

有人知道我如何能够将一些原始PCM字节[]转换为WAV字节[]吗?

我看到的例子都与将一个文件转换为另一个文件有关。

java pcm到wav

如何在java中从字节数组编写WAV文件?

非常感谢。

共有2个答案

柴嘉年
2023-03-14

已经有一段时间了,但我认为这可能会帮助一些人。这是我的解决方案——我将字节写回任意输出流(在我的例子中,它是servletoutputstream)。首先,我将WAV头(44字节)写入输出流,并写入pcm字节(您需要将pcm数据转换为字节数组)。我在html中使用了音频标记,并将src标记指定为我的api url,它工作得非常好。

public void streamCloudObject(OutputStream stream, InputStream pcmData) throws IOException {

    stream.write(WAVHeader.build(44100,5242880));
    //byte_chunk_size is stream buffer size, I have it as 1MB, so at a time you are streaming 1MB of bytes
    byte[] outBytes = new byte[BYTE_CHUNK_SIZE];

    while(true) {   
        int r = pcmData.read(outBytes);
        if(r == -1)
            break;      
        stream.write(outBytes,0,r); 

    }

}


public class WAVHeader {

private static final int CHUNK_SIZE = 36;
private static final int BIT_RATE_16 = 16;
private static final int MONO = 1;
private static final int HEADER_SIZE = 44;

//inputStreamLength - I send the pcm filesize here and I get it from s3.
public static byte[] build(int sampleRate,int inputStreamLength) {

    byte[] header = new byte[HEADER_SIZE];
    int srate = resp.getSampleRate();
    int channel = MONO;
    int format = BIT_RATE_16;
    long dataLength = inputStreamLength;

    long totalDataLen = dataLength + CHUNK_SIZE;
    long bitrate = srate * channel * format;

    header[0] = 'R'; 
    header[1] = 'I';
    header[2] = 'F';
    header[3] = 'F';
    header[4] = (byte) (totalDataLen & 0xff);
    header[5] = (byte) ((totalDataLen >> 8) & 0xff);
    header[6] = (byte) ((totalDataLen >> 16) & 0xff);
    header[7] = (byte) ((totalDataLen >> 24) & 0xff);
    header[8] = 'W';
    header[9] = 'A';
    header[10] = 'V';
    header[11] = 'E';
    header[12] = 'f'; 
    header[13] = 'm';
    header[14] = 't';
    header[15] = ' ';
    header[16] = (byte) format; 
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    header[20] = 1; 
    header[21] = 0;
    header[22] = (byte) channel; 
    header[23] = 0;
    header[24] = (byte) (srate & 0xff);
    header[25] = (byte) ((srate >> 8) & 0xff);
    header[26] = (byte) ((srate >> 16) & 0xff);
    header[27] = (byte) ((srate >> 24) & 0xff);
    header[28] = (byte) ((bitrate / 8) & 0xff);
    header[29] = (byte) (((bitrate / 8) >> 8) & 0xff);
    header[30] = (byte) (((bitrate / 8) >> 16) & 0xff);
    header[31] = (byte) (((bitrate / 8) >> 24) & 0xff);
    header[32] = (byte) ((channel * format) / 8); 
    header[33] = 0;
    header[34] = 16; 
    header[35] = 0;
    header[36] = 'd';
    header[37] = 'a';
    header[38] = 't';
    header[39] = 'a';
    header[40] = (byte) (dataLength  & 0xff);
    header[41] = (byte) ((dataLength >> 8) & 0xff);
    header[42] = (byte) ((dataLength >> 16) & 0xff);
    header[43] = (byte) ((dataLength >> 24) & 0xff);
    return header;
}
}
苏边浩
2023-03-14

我也陷入了同样的境地,以下是我如何解决问题的。

public static boolean getWavFile(String filePath, InputStream audioStream) throws IOException {

    boolean result = false;
    try {

        byte[] decodedData = IOUtils.toByteArray(audioStream);

        System.out.println(">>Decoded Data" + Arrays.toString(decodedData));
        File outFile = new File(filePath);
        AudioFormat format = new AudioFormat(8000, 16, 1, true, false);
        AudioSystem.write(new AudioInputStream(new ByteArrayInputStream(
                decodedData), format, decodedData.length), AudioFileFormat.Type.WAVE, outFile);
        result = true;
        return result;
    } catch (IOException ex) {
        System.out.println("<<getWavFile - impl" + ex);
        return result;

    }
}
 类似资料:
  • 我正在使用ADB拍摄android设备的屏幕截图,并将屏幕截图作为原始字节数据接收。 我知道通过的原始字节数据是rgba格式的 红色偏移量为0,绿色偏移量为8,蓝色偏移量为16,Alpha偏移量为24,每个值为1字节。这构成了整个字节数组。 我正在尝试将这个字节数组转换为C#中的位图,它在大多数情况下都工作正常,图像在各个方面看起来都是正确的,除了它带有一个“蓝色色调”——颜色是关闭的。 以下是我

  • 问题内容: 是否可以将字符串转换为字节数组,然后在Java或Android中将其转换回原始字符串? 我的目标是将一些字符串发送到微控制器(Arduino)并将其存储到EEPROM(仅1 KB)中。我尝试使用MD5哈希,但它似乎只是一种单向加密。我该怎么办? 问题答案: 我建议使用字符串的成员,但 使用显式编码 : 通过使用一种显式编码(以及一种支持所有Unicode的编码),您可以避免仅调用等问题

  • 我想将字节转换为JsonObject。我试着这样: 但我遇到编译器错误: 我怎么能这样呢?

  • 问题内容: 我想在GO中将字符串数组转换为字节数组,以便可以将其写到磁盘上。将字符串数组()解码为字节数组()的最佳解决方案是什么? 我正在考虑对字符串数组进行两次迭代,第一个迭代以获得字节数组所需的实际大小,然后第二个迭代写入每个元素的长度和实际字符串()。 解决方案必须能够以其他方式进行转换;从一个到一个。 问题答案: 让我们忽略一个事实,那就是走一秒钟。您需要做的第一件事是将序列化格式编组为

  • 我遇到了将字节字符串转换为字节数组的强制转换问题。 我有一个字符串[B@1a758cb。也就是Base64加密的String的主String"Gunjan"。这里的解密我想把加密的字节串转换成字节[]。 但是String.get字节[]不适合我。String.getBytes[]给出字节String的字节数。 我该怎么做??我是否必须迭代字节字符串中的每个字符并将其转换为字节[]?? 编辑 我使用

  • 问题内容: 我正在使用以下代码从外部程序获取标准输出: 方法返回一个字节数组: 但是,我想将输出作为普通的字符串使用。这样我就可以像这样打印它: 我认为这就是方法的用途,但是当我尝试使用它时,我又得到了相同的字节数组: 如何将字节值转换回字符串?我的意思是,使用”batteries”而不是手动进行操作。我希望它与Python 3兼容。 问题答案: 你需要解码bytes对象以产生一个字符串: