0

我有一个用 Java 编写的应用程序,我需要在其中播放音频。我使用 OpenAL(带有 java-openal 库)来完成任务,但是我想使用 OpenAL 不直接支持的 WSOLA。我找到了一个不错的 java-native 库,叫做 TarsosDSP,它支持 WSOLA。

该库使用标准 Java API 进行音频输出。在 SourceDataLine 设置期间出现此问题:

IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_UNSIGNED 16000.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian is supported.

我确保问题不是由缺少权限引起的(在 Linux 上以 root 身份运行 + 在 Windows 10 上尝试过),并且项目中没有使用其他 SourceDataLines。

在修改格式后,我发现当它从 PCM_UNSIGNED 更改为 PCM_SIGNED 时,格式被接受。这似乎是一个小问题,因为仅将字节范围形式从无符号移动到有符号应该很容易。但是很奇怪,它本身不支持。

那么,是否有一些我不必修改源数据的解决方案?

谢谢,扬

4

1 回答 1

1

您不必手动移动字节范围。创建 AudioInputStream 后,您将创建另一个 AudioInputStream,它具有签名格式并连接到第一个未签名流。如果您随后使用签名流读取数据,Sound API 会自动转换格式。这样您就不需要修改源数据。

File fileWithUnsignedFormat;

AudioInputStream sourceInputStream;
AudioInputStream targetInputStream;

AudioFormat sourceFormat;
AudioFormat targetFormat;

SourceDataLine sourceDataLine;

sourceInputStream = AudioSystem.getAudioInputStream(fileWithUnsignedFormat);
sourceFormat = sourceInputStream.getFormat();

targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
    sourceFormat.getSampleRate(), 
    sourceFormat.getSampleSizeInBits(), 
    sourceFormat.getChannels(), 
    sourceFormat.getFrameSize(), 
    sourceFormat.getFrameRate(), 
    false);

targetInputStream = AudioSystem.getAudioInputStream(targetFormat, sourceInputStream);

DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, targetFormat);
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);

sourceDataLine.open(targetFormat);
sourceLine.start();


// schematic
targetInputStream.read(byteArray, 0, byteArray.length);
sourceDataLine.write(byteArray, 0, byteArray.length);
于 2017-07-18T09:13:54.283 回答