I'm receiving some bytes[] through a WebSocketClient on my Android App. Those bytes are MP3 bytes : Layer III frame Single channel MPEG-1 no checksums 48 kHz, 32 kbit/s What I am trying to do is to write each bytes[] into an AudioTrack as soon as I receive one. Problem is, those bytes[] are MP3, which is a compressed format not accepted by the AudioTrack class. I'm trying to decode them into PCM. And here is how I create my Audio Track :
final AudioTrack player = new AudioTrack.Builder()
.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build())
.setAudioFormat(new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(48000)
.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
.build())
.setBufferSizeInBytes(AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT))
.build();
Finally here is what the server is sending me. I don't know how I should be building my Audio Track to match this format. The sample rate is set to 48000 Hz, I tried CHANNEL_OUT_STEREO and MONO. I tried all of the ENCODING parameters but I still have a very poor quality and a high pitched voice. Don't know what I'm doing wrong.
Stream #0:0: Audio: mp3 (libmp3lame), 48000 Hz, mono, s16p, 32 kb/s
EDIT: As I said in the comment, I tried something I found on a related post regarding the JLayer decoding, here is the new code:
public void addSample(byte[] data) throws BitstreamException, DecoderException {
Decoder decoder = new Decoder();
InputStream bis = new ByteArrayInputStream(data);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
Bitstream bits = new Bitstream(bis);
SampleBuffer pcmBuffer = (SampleBuffer) decoder.decodeFrame(bits.readFrame(), bits);
for (int i = 0; i < pcmBuffer.getBufferLength(); i++) {
if (pcmBuffer.getBuffer()[i] != 0) {
outStream.write(pcmBuffer.getBuffer()[i] & 0xff);
outStream.write((pcmBuffer.getBuffer()[i] >> 8) & 0xff);
}
}
System.out.println("--------");
for (int j = 0; j < outStream.toByteArray().length; j++) {
System.out.println(outStream.toByteArray()[j]);
}
System.out.println("--------");
mTrack.write(outStream.toByteArray(), 0, outStream.toByteArray().length);
bits.closeFrame();
}
Instead of directly writing the short[] data contained in the pcmBuffer, I decoded them in byte[] thanks to an outStream and some mask operation. I get the exact same result (robotic voice). But then as you can see I tried to loop inside the byteArray I'm writing into my AudioTrack, and I tried to print each data. Here is a sample of results :
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 48
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 46
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 44
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 44
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 45
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 48
11-20 10:18:42.331 1749-2268/? I/System.out: 0
So as I suspected, the data are actually written as (LEFT, RIGHT, LEFT, RIGHT)... I don't know how to get a real mono MP3 signal from those.