android - 在 AudioFlinger 中捕获音频数据并保存到原始 PCM 文件

标签 android c++ audio pcm audioflinger

经过一番研究,我发现这可以在Android的libaudioflinger中捕获音频数据。

我认为音频数据正在这里写入 HAL:

ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);

完整代码:https://android.googlesource.com/platform/frameworks/av/+/lollipop-release/services/audioflinger/Threads.cpp#2118

所以,我想将 mSinkBuffer + 偏移量保存到一个文件中(我预计它将是原始 PCM 音频文件)。我使用这些流将其写入文件:
std::ofstream audioData ("/data/audiodata.raw", std::fstream::app);
audioData.write((char *)mSinkBuffer + offset, count);
audioData.close();

该文件已成功写入,并且其中包含数据。
但是,当我使用 aplay 或 ffplay 播放 PCM 文件 (audiodata.raw) 时,我得到的唯一声音是噪音。
aplay -t raw -c 2 -f S16_LE -r 48000 audiodata.raw

我担心aplay的配置。所以我打印了一些 libaudioflinger 的日志:
10-07 10:14:54.575  1300  1366 I AudioFlinger: I/O handle: 13
10-07 10:14:54.575  1300  1366 I AudioFlinger: Standby: no
10-07 10:14:54.575  1300  1366 I AudioFlinger: Sample rate: 48000 Hz
10-07 10:14:54.575  1300  1366 I AudioFlinger: HAL frame count: 512
10-07 10:14:54.575  1300  1366 I AudioFlinger: HAL format: 0x1 (AUDIO_FORMAT_PCM_16_BIT)
10-07 10:14:54.575  1300  1366 I AudioFlinger: HAL buffer size: 2048 bytes
10-07 10:14:54.575  1300  1366 I AudioFlinger: Channel count: 2
10-07 10:14:54.575  1300  1366 I AudioFlinger: Channel mask: 0x00000003 (front-left, front-right)
10-07 10:14:54.575  1300  1366 I AudioFlinger: Processing format: 0x5 (AUDIO_FORMAT_PCM_FLOAT)
10-07 10:14:54.576  1300  1366 I AudioFlinger: Processing frame size: 8 bytes
10-07 10:14:54.576  1300  1366 I AudioFlinger: Pending config events:
10-07 10:14:54.576  1300  1366 I AudioFlinger:  none
10-07 10:14:54.576  1300  1366 I AudioFlinger: Output device: 0x2 (AUDIO_DEVICE_OUT_SPEAKER)
10-07 10:14:54.576  1300  1366 I AudioFlinger: Input device: 0 (AUDIO_DEVICE_NONE)
10-07 10:14:54.576  1300  1366 I AudioFlinger: Audio source: 0 (default)

我不知道我做错了什么。请帮我!

提前谢谢你!

最佳答案

以追加 |二进制模式打开文件

std::ofstream audioData ("/data/audiodata.raw", std::fstream::app | std::fstream::binary);

binary - binary - Operations are performed in binary mode rather than text.



原始 PCM 缓冲区应以二进制模式写入。

请检查代码以了解字节数和计数之间的差异
(添加了一些评论供引用,希望这能解决您的问题)
if (mNormalSink != 0) {

    /* Count is the number of Frames or sample written != bytes  */
    const size_t count = mBytesRemaining / mFrameSize;

    ATRACE_BEGIN("write");
    // update the setpoint when AudioFlinger::mScreenState changes
    uint32_t screenState = AudioFlinger::mScreenState;
    if (screenState != mScreenState) {
        mScreenState = screenState;
        MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
        if (pipe != NULL) {
            pipe->setAvgFrames((mScreenState & 1) ?
                    (pipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
        }
    }
    ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);

    ATRACE_END();
    if (framesWritten > 0) {
        bytesWritten = framesWritten * mFrameSize;
        // std::ofstream audioData ("/data/audiodata.raw", std::fstream::binary);
        /* File write or stream write is the number of bytes written to the file */
        audioData.write((char *)mSinkBuffer + offset, bytesWritten);
        // audioData.close();
    } else {
        bytesWritten = framesWritten;
    }
// otherwise use the HAL / AudioStreamOut directly
}

Audacity - 打开原始文件

文件 -> 导入 -> 原始数据

选择原始文件路径

根据您附加的原始文件。

使用这些设置

编码:32 位浮点数

字节顺序:小尾数

声道:2声道(立体声)

起始偏移量:0

进口数量:100

采样率:48000

文件播放正常,没有任何故障/噪音。

关于android - 在 AudioFlinger 中捕获音频数据并保存到原始 PCM 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58254486/

相关文章:

Android:2个触摸位置之间的物理距离

c++ - std::find_if 中的谓词仿函数不是引用

C++如何将参数传递给嵌套函数之一?

android - 需要一个简单的录音例子

iphone - 您如何在启动时播放音乐?

java - Android:如何从 fragment 中的主动行为中获取媒体播放器对象?

java - 在android中的静态 map 上使用gps?

java - 我有一个图像,我希望每次单击按钮时它都会变大

android - 用户输入的撇号使 android 应用程序崩溃(与 SQL 相关)

c++ - 如何使用 condition_variable 来真正 wait_for 不超过一定的持续时间