我有一个用Java编写的应用程序,需要在其中播放音频。我使用OpenAL(带有java-openal库)来完成任务,但是我想使用WSOLA,而OpenAL不直接支持WSOLA。我找到了一个名为TarsosDSP的不错的Java本机库,它支持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时,该格式可以接受。这似乎是一个小问题,因为仅将无符号的字节范围形式移动到带符号应该很容易。但是奇怪的是它本身不支持。

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

谢谢,扬

最佳答案

您不必手动移动字节范围。创建AudioInputStream之后,您将创建另一个AudioInputStream,该音频InputStream具有签名格式,并且连接到第一个未签名的流。如果随后使用签名流读取数据,则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);

关于java - SourceDataLine格式支持问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45132587/

10-09 18:06
查看更多