我正在使用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://dev59.com/3Wgv5IYBdhLWcg3wKtlB#12347176声音会变得失真和抖动:
at.write(output.getBuffer(), 0, output.getBuffer().length);
becomes:
byte[] array = ShortToByte_Twiddle_Method(output.getBuffer());
at.write(array, 0, array.length);
我是否做错了什么,我该怎么解决?不幸的是,我需要将pcm数据转换为字节数组以供我使用的第三方库。如果有影响,文件的采样率为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)
编辑:我很想把赏金分开,但我最终将赏金给了Bill,接受了Neil的答案。两位都非常有帮助。对于那些好奇的人,我最终重新编写了Sonic本地代码,这帮助我推进了进程。