我使用 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 数据放在我正在使用的另一个 3rd 方库的字节数组中。如果这很重要,文件是 22kHz,这就是实例化的方式:
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 原生代码,它帮助我完成了这个过程。