解码audio文件并重新编码为所需的PCM格式:44,100 kHz,2个通道,16位

我想将audio文件解码为原始PCM数据,将其stream式传输到本地networking中的播放设备。 我使用了API级别为16的新MediaExtractor和MediaCodec类。 该设备要求PCM数据在44100kHz,具有2个通道和16位样本大小 。 只要input文件大致符合这些要求,这工作正常。 但是,无论何时我正在解码一个MP3文件,例如,使用32,000 kHz的采样率,也许只有一个通道,那么我不会从MediaCodec类获得所需的输出。

看来我不能指定MediaCodec类的输出格式 。 所以我决定实例化另一个MediaCodec对象,将原始数据重新编码成我想要的格式。 根据Android 4.1 支持的媒体格式列表,Android支持编码PCM / Wave。 但是, 我无法创build一个MediaCodec对象,编码PCM / Wave 。 我试着将各种MIMEtypes传递给MediaCodec.createEncoderByType(type); 但是我总是以IOExceptionexception失败:

java.io.IOException: Failed to allocate component instance at android.media.MediaCodec.native_setup(Native Method) at android.media.MediaCodec.<init>(MediaCodec.java:210) at android.media.MediaCodec.createEncoderByType(MediaCodec.java:194) [..] 

有没有人能够成功地创build一个MediaCodec实例,编码为PCM / Wave,并可以提供一个工作的例子?

Solutions Collecting From Web of "解码audio文件并重新编码为所需的PCM格式:44,100 kHz,2个通道,16位"

根据我们在评论中的对话,这个答案适用于使用OpenSL将audio数据解码到PCM。 不幸的是,我无法使用MediaCodec类提供类似的答案。

首先,设置一个Android NDK项目(使用Eclipse:右键单击项目,Android Tools – > Add Native support …)。 然后,在创build的Android.mk文件中,至less需要链接到OpenSL库:

 LOCAL_LDLIBS += -lOpenSLES 

如果你对NDK项目不太舒服,那么在旧的互联网上就有很多教程,例如这里和这里 。

一旦你有一个NDK项目的工作,一般的目标将是build立一个audio播放器,作为一个PCM解码器。 在NDK样本中实际上有一个例子确实如此。 这要比制作一个最低限度function的工具复杂一点,但它应该让你走。 有一个很容易理解的描述这个链接发生了什么(search“解码audio到PCM”)。 我在评论中为您提供了相关OpenSL规范的链接,但是它又是一次。 指定数据接收器时需要使用的SLDataFormat_PCM结构如下所示:

 SLDataFormat_PCM pcm = { SL_DATAFORMAT_PCM, 2, // numChannels SL_SAMPLINGRATE_44_1, // samplesPerSec SL_PCMSAMPLEFORMAT_FIXED_16, // bitsPerSample SL_PCMSAMPLEFORMAT_FIXED_16, // containerSize SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, // channelMask SL_BYTEORDER_LITTLEENDIAN // endianness }; 

遵循示例和描述性指南,您将定义一个带有Android简单缓冲区队列数据定位器和上述数据格式的SLDataSink。 玩家应该为您提供一系列包含正确格式数据的缓冲区。 然后,您可以将该数据传回给Java,或(更好地)从本地代码中传输数据。