Android Studio - libmp3lame NDK

时间:2017-11-21 09:53:04

标签: android android-ndk java-native-interface mp3

我目前正在尝试将libmp3lame实现到我的Android应用程序中,以便将MP3数据解码为PCM。

要使用libmp3lame,我需要使用JNI / NDK实现,并将MP3解码为PCM我需要使用libmp3lame中的hip_decode()函数。

此函数实例化为“lame.h”文件:

int CDECL hip_decode( hip_t           gfp
                , unsigned char * mp3buf
                , size_t          len
                , short           pcm_l[]
                , short           pcm_r[]
                );

我的应用程序是这样的: 我从WebSocket收到一个单声道MP3样本。我需要将此示例从MP3解码为PCM,然后将其写入我的AudioTrack进行播放。它是实时流,所以我需要尽可能低的延迟。我正在使用JLayer,我完全可以理解发言者的说法,但我有一个“哈希”问题/机器人声音。似乎我在每个样本的开头有一些0值,它引起了一些奇怪的效果。现在我需要对libmp3lame做同样的事情。所以我想做的是以下内容。每次调用WebSocket甚至接收时,我都需要接收字节数组(包含音频数据)并将其解码为PCM。我需要在PCM中使用byte []或short []然后在音轨中播放它。问题是我不确定如何使用hip_decode这样做。我真的不熟悉C编程,所以可能有一个非常简单的方法来做,但我不能这样做。现在在我的wrapper.c中我有这个:

JNIEXPORT void JNICALL Java_com_example_jneb_myapplication_MainActivity_decoderInit(JNIEnv *env, jobject jobj,
    ) {
    hip = hip_decode_init();

}

我不确定使用hip_decode函数需要什么pcm_l和pcm_r。以下是有关该功能的更多信息:

/*********************************************************************
* 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
*
*********************************************************************/

编辑: 感谢bukkojot回答我已经能够理解什么是pcm_l& pcm_r用于。

以下是我的代码的更新:

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;

}

现在pcmBuffer只返回0值,而hip_decode也只返回0值。该文档说,如果hip_decode返回0,则hip_decode函数“在我们完成解码之前需要更多数据”。我已经给了函数我所有的数据了。我对hip_decode函数做错了什么?

1 个答案:

答案 0 :(得分:2)

  

不确定使用hip_decode需要什么pcm_l和pcm_r   功能

这是缓冲区的指针,其中将写入解码的PCM。

Alloc某处有足够的内存用于未压缩的声音,如:

signed short *pcm_l=malloc(1000000); // make sure it's enough
signed short *pcm_r=malloc(1000000);

然后将它们传递给解码功能。函数将返回有用样本的数量。将此数据传递给Java部分并写入AudioTrack。