Reputation: 309
I am currently trying to implement libmp3lame into my Android Application in order to decode MP3 data into PCM.
To use libmp3lame, I need to use JNI/NDK implementation, and to decode MP3 into PCM I need to use the hip_decode() function from libmp3lame.
This function is instantiated like this the "lame.h" file:
int CDECL hip_decode( hip_t gfp
, unsigned char * mp3buf
, size_t len
, short pcm_l[]
, short pcm_r[]
);
My application works like this: I receive one mono MP3 sample from a WebSocket. I need to decode this sample from MP3 to PCM and then write it into my AudioTrack to play it. It is live stream so I need the lowest latency possible. I was using JLayer and I could understand perfectly what was the speaker saying but I had a "hash" problem / robotic voice. It seemed like I had some 0 value at the beginning of each sample and it caused some weird effect. Now I need to do the same with libmp3lame. So what I want to do is the following. Everytime my WebSocket even reception is called, I need to take the byte array received (containing the audio data) and decode it into PCM. I need to have byte[] or short[] in PCM and then play it in audio track. Problem is I'm not sure how to use the hip_decode to do so. I'm really not familiar with C programming so there might be a very simple way to do it but I just can't do it. Right now in my wrapper.c I have this :
JNIEXPORT void JNICALL Java_com_example_jneb_myapplication_MainActivity_decoderInit(JNIEnv *env, jobject jobj,
) {
hip = hip_decode_init();
}
I'm not sure what are the pcm_l and pcm_r needed to use the hip_decode function. Here is some more information regarding the function :
/*********************************************************************
* input 1 mp3 frame, output (maybe) pcm data.
*
* nout = hip_decode(hip, mp3buf,len,pcm_l,pcm_r);
*
* input:
* len : number of bytes of mp3 data in mp3buf
* mp3buf[len] : mp3 data to be decoded
*
* output:
* nout: -1 : decoding error
* 0 : need more data before we can complete the decode
* >0 : returned 'nout' samples worth of data in pcm_l,pcm_r
* pcm_l[nout] : left channel data
* pcm_r[nout] : right channel data
*
*********************************************************************/
EDIT: Thanks to bukkojot answer I've been able to understand what were pcm_l & pcm_r used for.
Here is an update of my code :
JNIEXPORT jshortArray JNICALL Java_com_example_jneb_myapplication_AudioTrackClass_decoderInit(JNIEnv *env, jobject jobj,
jbyteArray data, jint size) {
jsize mp3Len = (*env)->GetArrayLength(env, data);
// Print the data.length = 96
LOGI("JNI integer: %d", mp3Len);
// mp3 contains all 96 values
jbyte *mp3 = (*env)->GetByteArrayElements(env, data, 0);
// Trying to decode mp3 into PCM
int x = hip_decode(hip, (unsigned char*) mp3, (size_t) mp3Len, pcm_l, pcm_r);
jshortArray pcmBuffer;
pcmBuffer = (*env)->NewShortArray(env, mp3Len);
(*env)->SetShortArrayRegion(env, pcmBuffer, 0, mp3Len, pcm_l);
// Releasing byte array
(*env)->ReleaseByteArrayElements(env, data, mp3, 0);
// Returning
return pcmBuffer;
}
Right now pcmBuffer only return 0 value, and the hip_decode only returns 0 value too. The doc says that if hip_decode return 0 then the hip_decode function "need more data before we can complete the decode". I'm already giving the function all the data I have. What am I doing wrong with the hip_decode function ?
Upvotes: 0
Views: 439
Reputation: 1530
'm not sure what are the pcm_l and pcm_r needed to use the hip_decode function.
This is the pointers to buffers, where decoded PCM will be written.
Alloc somewhere enough memory for uncompressed sound like:
signed short *pcm_l=malloc(1000000); // make sure it's enough
signed short *pcm_r=malloc(1000000);
And then just pass them to decoding function. Function will return number of useful samples. Pass this data to Java part and write to AudioTrack.
Upvotes: 2