android - 解码音频文件并重新编码为所需的 PCM 格式 : 44, 100 kHz,2 channel ,16 位

标签 android audio pcm android-mediacodec mediaextractor

我想将音频文件解码为原始 PCM 数据,以将其流式传输到本地网络中的播放设备。我使用新的 MediaExtractorMediaCodec API 级别 16 引入的类。该设备要求 PCM 数据为 44,100 kHz,具有 2 个 channel 和 16 位样本大小。只要输入文件大致符合这些要求,这就可以正常工作。但是,每当我解码使用 32,000 kHz 采样率并且可能只有一个 channel 的 MP3 文件时,我就无法从 MediaCodec 类获得所需的输出。

看来我无法指定 MediaCodec 类的输出格式。所以我决定实例化另一个 MediaCodec 对象以将原始数据重新编码为我想要的格式。根据列表supported media formats Android 自 Android 4.1 起支持编码为 PCM/Wave。但是,我无法创建编码为 PCM/Wave 的 MediaCodec 对象。我尝试将各种 MIME 类型传递给 MediaCodec.createEncoderByType(type);但我总是因 IOException 而失败:

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)
[..]

你们中有没有人能够成功地创建编码为 PCM/Wave 的 MediaCodec 实例,并且可以为我提供一个工作示例?

最佳答案

根据我们在评论中的对话,此答案涉及使用 OpenSL 将音频数据解码为 PCM。不幸的是,我无法使用 MediaCodec 类提供类似的答案。

首先,设置一个 Android NDK 项目(使用 Eclipse:右键单击项目,Android 工具 -> 添加 native 支持...)。然后,在创建的 Android.mk 文件中,至少您需要链接到 OpenSL 库:

LOCAL_LDLIBS += -lOpenSLES

如果您对 NDK 项目还不熟悉,旧的互联网上有大量教程,例如 herehere .

一旦您的 NDK 项目开始运行,总体目标将是设置一个充当 PCM 解码器的音频播放器。实际上有一个 example in the NDK samples正是这样做的。这比制作一个功能最少的工具要复杂一些,但它应该能让你继续下去。对正在发生的事情有一个非常容易理解的描述at this link (搜索“将音频解码为 PCM”)。我为您提供了相关 OpenSL spec 的链接在评论中,但又出现了。在指定数据接收器时需要使用的 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,或者(更好)从 native 代码流式传输数据。

关于android - 解码音频文件并重新编码为所需的 PCM 格式 : 44, 100 kHz,2 channel ,16 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20635845/

相关文章:

java - 将 16 位 pcm 转换为 8 位

android - 从 Android 中的解码声音文件绘制音频波形

iphone - 在后台播放音频文件(多任务)

javascript - HTML5 <音频>:单击下一首歌曲时停止加载/缓冲

android - 在 Activity 转换时保持 admob 广告

android - 查找 Android 应用程序的包名称以使用 Intent 从 Web 启动 Market 应用程序

c# - 来自 .mp4 的 channel 音频?

java - Android 将 PCM 和 MP3 合并为 AAC

android - 如何禁用或删除屏幕键盘上的设置按钮

android - 在Android的应用程序背景中播放连续音频?