如何将PCM流分割成每个通道的音频输入流?

问题描述 投票:0回答:1

我有一个立体声 AudioInputStream 我想把它分成两个单体。AudioInputStream一个用于左声道,一个用于右声道的立体声流。我怎么做呢?

注意:我已经测试了以下问题的答案,但没有任何效果(这就是为什么我再次询问的原因)。 我已经测试了下面问题的答案,但没有任何工作对我来说(这就是为什么我再次问)。

如何在java中把一个Wav文件分割成多个通道?

这是我想让它工作的方法(主要是来自上面的链接)。在下面的代码中,while循环无限运行。readsize 始终是4(或其他什么 sampleInBytes * 2 是),它永远不会变成-1(这意味着它是流的终点),所以它永远不会断。

   AudioInputStream originalAudioInputStream = null;
    try {
        originalAudioInputStream = AudioSystem.getAudioInputStream(audiofile);
    } catch (UnsupportedAudioFileException e) {
        //file not supported
    } catch (IOException e) {
        //error
    }
    //read file and convert it to PCM SIGNED big endian
    AudioFormat destaf = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
            originalAudioInputStream.getFormat().getSampleRate(),
            originalAudioInputStream.getFormat().getSampleSizeInBits(),
            originalAudioInputStream.getFormat().getChannels(),
            originalAudioInputStream.getFormat().getSampleSizeInBits() / 8 * originalAudioInputStream.getFormat().getChannels(),
            originalAudioInputStream.getFormat().getSampleRate(), true);
    AudioInputStream signedBigEndianInputStream = AudioSystem.getAudioInputStream(destaf, originalAudioInputStream);

    //split stereo AudioInputStream
    ByteArrayOutputStream leftbaos = new ByteArrayOutputStream();
    ByteArrayOutputStream rightbaos = new ByteArrayOutputStream();

    byte[] bytes = new byte[(signedBigEndianInputStream.getFormat().getSampleSizeInBits()/8)*2];

    while (true) {

        int readsize = 0;
        try {
            readsize = signedBigEndianInputStream.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }  

        if(readsize==-1){
            break;
        }

        rightbaos.write(bytes,0,bytes.length/2);
        leftbaos.write(bytes,bytes.length/2,bytes.length/2);
    }

    byte[] leftData = leftbaos.toByteArray();
    byte[] rightData = rightbaos.toByteArray();

    AudioFormat outFormat = new AudioFormat(signedBigEndianInputStream.getFormat().getEncoding(),signedBigEndianInputStream.getFormat().getSampleRate(),signedBigEndianInputStream.getFormat().getSampleSizeInBits(),1,signedBigEndianInputStream.getFormat().getFrameSize()/2, signedBigEndianInputStream.getFormat().getFrameRate(),signedBigEndianInputStream.getFormat().isBigEndian());

    ByteArrayInputStream leftbais = new ByteArrayInputStream(leftData);
    AudioInputStream leftoutputAIS = new AudioInputStream(leftbais, outFormat, leftData.length / outFormat.getFrameSize());

    ByteArrayInputStream rightbais = new ByteArrayInputStream(rightData);
    AudioInputStream rightoutputAIS = new AudioInputStream(rightbais, outFormat, rightData.length / outFormat.getFrameSize());

    //close inputstreams
    try {
        rightoutputAIS.close();
        leftoutputAIS.close();
        rightbais.close();
        leftbais.close();
        rightbaos.close();
        leftbaos.close();
        signedBigEndianInputStream.close();
        originalAudioInputStream.close();

    } catch (IOException e) {
        //error
    }

谢谢!我有一个立体声音频输入流,我想把它分成两个单声道的音频输入流。

java javasound
1个回答
0
投票

你假设音频被存储在两个块中。

  1. 所有左声道采样
  2. 所有正确的样品

相反,音频通常存储在一个 交错式.

就是说:

  1. 左边一个样本
  2. 一个右边的样品
  3. 一个左样
  4. 一个右边的样品
  5. ... (你懂的)

为了分离两个流,你必须做这样的事情。

[...]

final int bytesPerSample = destaf.getSampleSizeInBits() / 8;
final int channels = 2;

while (true) {
    int readsize = 0;
    try {
        readsize = signedBigEndianInputStream.read(bytes);
    } catch (IOException e) {
        e.printStackTrace();
    }  

    if (readsize==-1){
        break;
    }
    for (int sample=0; sample<readsize/channels/bytesPerSample;sample++) {
        final int offset = sample * bytesPerSample * channels;
        leftbaos.write(bytes, offset, bytesPerSample);
        rightbaos.write(bytes, offset + bytesPerSample, bytesPerSample);
    }    
}
[...]
© www.soinside.com 2019 - 2024. All rights reserved.