我有一个用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时,格式被接受。这似乎是一个小问题,因为只将unsigned的字节范围移动到signed应该很容易。然而,它本身不受支持是奇怪的。
那么,是否有一些我不需要修改源数据的解决方案?
谢谢,Jan
答案 0 :(得分: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);