Capturing audio data and save to raw PCM file in AudioFlinger

6

After some research, I find out this is possible to capture the audio data in libaudioflinger of Android.

I think the audio data is being written to HAL in here:

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

Full code: https://android.googlesource.com/platform/frameworks/av/+/lollipop-release/services/audioflinger/Threads.cpp#2118

So, I would like to save the mSinkBuffer + offset to a file (which I expected it will be raw PCM audio file). I using those stream to write it to file:

std::ofstream audioData ("/data/audiodata.raw", std::fstream::app);
audioData.write((char *)mSinkBuffer + offset, count);
audioData.close();

The file is successfully written and it has data in it. But, when I play the PCM file (audiodata.raw) with aplay or ffplay, the only sound I got is noise.

aplay -t raw -c 2 -f S16_LE -r 48000 audiodata.raw

I was worry about the config of aplay. So I print some log of the 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)

I don't know what I did wrong. Please help me!

Thank you in advanced!

android
c++
audio
pcm
audioflinger
asked on Stack Overflow Oct 6, 2019 by Banana droid • edited Oct 7, 2019 by Banana droid

2 Answers

1

Open The file in append |binary mode

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

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

Raw PCM buffer should be written in binary mode.

Please check the code for the difference between the bytes and count ( added some comments for the reference , I hope this will solve your problem)

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 - Open a raw file

File -> Import -> raw data

Select the raw file path

Based on your raw file attached.

Use these Setting

Encoding : 32 -bit float

Byte order: Little Endian

Channels : 2 channels ( stereo)

Start offset : 0

Amount to import : 100

Sample Rate : 48000

File plays properly without any glitches/noise.

answered on Stack Overflow Oct 10, 2019 by mail2subhajit • edited Oct 24, 2019 by mail2subhajit
0

When you have to play your raw file you must use a codec format for the sound frames,such as wav or mp3 etc. Try to pass the raw data to a wav WAVEFORMAT defined in winmm and get audio from the devices that can be opened and closed via the WAVEFORMAT types in C++.

answered on Stack Overflow Oct 10, 2019 by SteveTheGrk

User contributions licensed under CC BY-SA 3.0