gpt4 book ai didi

java - 如何将PCM流拆分为每个 channel 的AudioInputStreams?

转载 作者:行者123 更新时间:2023-12-01 16:58:35 24 4
gpt4 key购买 nike

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

注意:我已经测试了以下问题的答案,但没有任何效果(这就是我再次询问的原因)。

How to split a Wav file into channels in java?

这是我正在尝试的工作(主要来自上面的链接)。在下面的代码中,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
}

谢谢!

最佳答案

您假设音频存储在两个 block 中:

  1. 所有剩余样本
  2. 所有正确的示例

相反,音频通常存储在 interleaved fashion 中.

即:

  1. 剩下一个样本
  2. 一个正确的样本
  3. 剩下一个样本
  4. 一个正确的样本
  5. ...(你明白了)

为了分离两个流,您必须执行以下操作:

// just to show which types are used
// i.e., initialization is not shown
AudioFormat destaf;
ByteArrayOutputStream leftbaos;
ByteArrayOutputStream rightbaos;
AudioInputStream signedBigEndianInputStream;
byte[] bytes;

[...]

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);
}
}
[...]

关于java - 如何将PCM流拆分为每个 channel 的AudioInputStreams?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61549655/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com