我使用 jLayer 来解码 MP3 数据,通过以下调用:
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
此调用返回解码后的数据,返回一个short[]数组。output.getBuffer();
当我使用该方法调用 AudioTrack write() 时,它在循环文件时播放得很好:
at.write(output.getBuffer(), 0, output.getBuffer().length);
但是,当我使用此答案中的任何方法将 Short[] 数组转换为 byte[] 数组时:https://stackoverflow.com/a/12347176/1176436声音变得扭曲和颤抖:
at.write(output.getBuffer(), 0, output.getBuffer().length);
变成:
byte[] array = ShortToByte_Twiddle_Method(output.getBuffer());
at.write(array, 0, array.length);
我做错了什么吗?我能做些什么来解决它?不幸的是,我需要将 pcm 数据放在我正在使用的另一个第三方库的字节数组中。如果重要的话,文件是 22kHz,这就是 at 的实例化方式:
at = new AudioTrack(AudioManager.STREAM_MUSIC, 22050, AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT, 10000 /* 10 second buffer */,
AudioTrack.MODE_STREAM);
预先非常感谢您。
编辑:这就是我现在实例化 AudioTrack 变量的方式。因此,对于 44kHz 文件,发送的值为 44100,而对于 22kHz 文件,发送的值为 22050。
at = new AudioTrack(AudioManager.STREAM_MUSIC, decoder.getOutputFrequency(),
decoder.getOutputChannels() > 1 ? AudioFormat.CHANNEL_OUT_STEREO : AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, 10000 /* 10 second buffer */,
AudioTrack.MODE_STREAM);
这是解码方法:
public byte[] decode(InputStream inputStream, int startMs, int maxMs) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
float totalMs = 0;
boolean seeking = true;
try {
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (!done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();
if (totalMs >= startMs) {
seeking = false;
}
if (!seeking) {
// logger.debug("Handling header: " + frameHeader.layer_string());
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8) & 0xff);
}
}
if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}
return outStream.toByteArray();
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
throw new IOException("Decoder error: " + e);
}
}
听起来是这样的(等待几秒钟):https://vimeo.com/60951237(这是实际的文件:http://www.tonycuffe.com/mp3/tail%20toddle.mp3)
编辑:我本来很想平分赏金,但我把赏金给了比尔,把公认的答案给了尼尔。两者都提供了巨大的帮助。对于那些想知道的人,我最终重写了 Sonic 本机代码,这帮助我完成了整个过程。