【问题标题】:Need Help for this flow (AudioInputStream -> byte Array -> AudioOutputStream)需要此流程的帮助(AudioInputStream -> byte Array -> AudioOutputStream)
【发布时间】:2014-11-06 07:18:19
【问题描述】:

我正在制作一个修改原始声音的程序。

我的程序的进程到这里了。

  1. AudioInputStream 获取声音
  2. 将声音数据更改为字节数组。(我的AudioFormat的帧大小4。所以,我将使用长度为4)
  3. 修改字节数组(类似于“对每个元素乘以-1”
  4. 将修改后的字节数组发送到AudioOutputStream
  5. 播放声音。

我做了过程 1、2 和 3。

这是我的流程 1、2、3 的 CODE

try {
  byte[] packet = new byte[4];
  int result;

  while((result = audioInputStream.read(packet)) != -1)
    for(int i = 0;i < 4;i++)
      reflectedPacket[i] = (byte)(-1 * packet[i]);

      //I think I have to do something to send packet to AudioOutputStream in here
  }
catch(IOException ioe) {
  System.out.println(ioe.getMessage());
}

但是不知道怎么做流程4,将修改后的字节数组发送到AudioOutputStream

我看到一个使用 ByteArrayInputStream 的源。

但是,它是读取文件的源,而不是 AudioInput :(

如何进行流程 4 和流程 5?

【问题讨论】:

    标签: java arrays audio bytearray javasound


    【解决方案1】:

    您要查找的“AudioOutputStream”称为SourceDataLine。可以从AudioSystem获取,有tutorial here

    但是,作为警告,

    我的 AudioFormat 的帧大小是 4。

    除非您的音频是具有 4 个通道的 8 位音频(我几乎可以保证不是),否则否定字节听起来就像失真。这是因为帧中的字节被“打包”了,例如:

    big-endian 16 位立体声 PCM 帧 b[0] b[1] b[2] b[3] 00000000 00000000 00000000 00000000 在哪里: - b[0] = 左声道高字节 - b[1] = 左声道低字节 - b[2] = 右声道高字节 - b[3] = 右声道低字节

    要解压这个框架,你可以这样做

    int ch0 = (b[0] << 8) | (b[1] & 0xFF);
    int ch1 = (b[2] << 8) | (b[3] & 0xFF);
    

    要打包这个框架,你可以这样做

    b[0] = (byte)((ch0 >>> 8) & 0xFF);
    b[1] = (byte)( ch0        & 0xFF);
    b[2] = (byte)((ch1 >>> 8) & 0xFF);
    b[3] = (byte)( ch1        & 0xFF);
    

    对于little-endian,高低字节颠倒。

    另请参阅:JSR FAQ

    【讨论】:

    • 感谢您的回答!很抱歉,您能否详细介绍一下AudioInputStream 中的字节数组是什么样子的?我注意到来自 AudioInputStream 的 4 字节数组表示左通道高字节 / 左低 / 右高 / 右低。我从未见过这样的解释。
    • 我想做的是主动降噪。所以我必须使输入声音(AudioInputStream)反相。并将其写入扬声器。对主动降噪有什么建议吗?
    • “AudioInputStream 中的字节数组长什么样?” 这确实需要冗长的解释。 Java Sound Resources FAQ 包含很多解释这类事情的答案,特别是'How are samples organized in a byte array/stream?'
    • ANC,这个想法很简单,但它假设您已经记录了外部噪音。您翻转噪声信号并将其添加到播放中,瞧,噪声似乎消失了。不太确定您要寻求什么建议。在实际系统中,您需要校准噪声的幅度,因为如果用户调高音量,翻转的噪声将变得可听。作为硬件设备,它可能做得最好。如果你只是想学习,你可以自己校准。
    【解决方案2】:

    我认为您没有正确地将 audioInputStream 读入 byte 数组。尝试将您的 while 和嵌套的 for 循环替换为:

    int framesize = 4;
    byte[] packet = new byte[framesize];
    int numBytesRead = audioInputStream.read(packet, 0, framesize);
    for(int i = 0; i < numBytesRead; i++)
      reflectedPacket[i] = (byte)(-1 * packet[i]);
    

    顺便说一句,我认为修改音频流的方式非常糟糕。请查看Java Sound Info 页面和post 以获得一些有用的链接来修改音频流。

    无论如何....一旦你修改了你的音频流,你可以使用AudioSystem.getAudioInputStream(java.io.InputStream),来执行你的第4步,像这样:

    AudioInputStream newStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(reflectedPacket));
    

    最后,你需要Clip接口来播放声音:

    Clip clip = AudioSystem.getClip();
    clip.open(newStream);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2016-04-12
      • 2018-08-28
      • 2013-10-09
      相关资源
      最近更新 更多