2
votes

I am currently working on mp3 decoding with javalayer 1.1.

So I want to receive the raw PCM data from my 44100 Hz, 16bit, Mp3s. It is perfectly working fine with stereo mp3s, but i have strange issues with mono mp3s.

Here some code.

InputStream data = c.getResources().openRawResource(resId);
Bitstream bitstream = new Bitstream(data);
Decoder decoder = new Decoder();
while(thereIsData) {
  Head frameHeader = bitstream.readFrame();
  SampleBuffer buffer = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
  short[] pcmBuffer = buffer.getBuffer();

  // Do some stuff with pcm (For example creating a wav file )

  bitstream.closeFrame();
}

buffer.getChannelCount() == 1, buffer.getFrequency() == 41000

So... The Problem is. If I create a 44100 Hz, mono Channel, 16-bit WaveFile and put it in Audacity to see the waves. The sound is periodically 0,like: (200ms Sound)...(200ms NoSound)...(200ms Sound)...(200ms NoSound)

This goes also for the pcm data before writing to .wav... (Yeahi syso all the stuff)

So one may think, well there got to be zero-frames or sth. in there... So I cut off all frames with only 0 values in it. This results in slighty shorter zero breaks in the wav file. Means to me, there must be partial zero frames. So I cut ALL zero values from the pcm data... And as weird as it seems, this worked. The file sounds OK.

But this cant be the solution. I still dont know why there are these false zero values. And I need silence in my mp3's as well.

I'd appreciate every explanation hint. Thanks

2
Were you able to resolve this issue?ajacian81
I trust the thereIsData parameter is a Boolean? And where do you set it to false? I am trying to make a similar thing, but I can't get this to workDijkeMark
In this case it is just a placeholder for actually checking, if there is more data. I can't really remember, but I think, you can check if the next chunk is valid after you read the next frame header. There you can call sth. that determines if this header is invalid and therefore it is EOS.xeed

2 Answers

4
votes

I got it working, converting to byte[], using this code:

ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
int divider = 1;
if (SAMPLE_RATE < 44100) divider *= 2;
if (CHANNELS == 1) divider *= 2;

[...]

short[] pcmBuffer = buffer.getBuffer();    
for (int i=0; i<pcm.length/divider; i++) {
    outStream.write(pcm[i] & 0xff);
    outStream.write((pcm[i] >> 8 ) & 0xff);
}

The key was the divider parameter, that is 1 in stereo-44, 2 in mono-44 and 4 in mono-22. Didn't try yet other combinations.

2
votes

Hm... My answer comes a bit late.. Sorry for that.

I completly solved the issue.

JLayer did some weird stuff. If the input mp3 is Stereo, the values in the pcmbuffer are encoded like this: leftchannel, rightchannel, leftchannel, ... This is how it should be. But if the input mp3 is Mono the I get the same amount of samples in the pcmbuffer. But its not like: monochannel, 0, monochannel, 0 The whole data is in the first half of the pcmbuffer and the second half is all 0. So you just need to cut off the second half.