如何dump audio資料定位雜音問題

光著腳丫行一生發表於2017-03-29

我們在分析雜音等問題的時候, 只抓adb log是不夠的, dump audio的資料能直觀快速的判斷是哪一塊出了問題, 這裡只針對高通平臺。

1. dump audioflinger的資料
/frameworks/av/services/audioflinger/Tracks.cpp#getNextBuffer

// AudioBufferProvider interface
status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
        AudioBufferProvider::Buffer* buffer)
{
    ServerProxy::Buffer buf;
    size_t desiredFrames = buffer->frameCount;
    buf.mFrameCount = desiredFrames;
    status_t status = mServerProxy->obtainBuffer(&buf);
    buffer->frameCount = buf.mFrameCount;
    buffer->raw = buf.mRaw;
    if (buf.mFrameCount == 0) {
        mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
    } else {
        mAudioTrackServerProxy->tallyUnderrunFrames(0);
    }
    //JaychouNote: dump audio flinger data begin.
        int tmpFd = ::open("/data/misc/audio/dumpTrack.pcm", O_CREAT | O_WRONLY | O_APPEND, 0777);
        if ( tmpFd < 0 ) {
            ALOGE("Tracks.cpp Fail to open dumpTrack file");
        } else {
            ::write(tmpFd, buffer->raw, buffer->frameCount * TrackBase::mChannelCount * 2);
            ::close(tmpFd);
        }
        //JaychouNote: dump audio flinger data end.
    return status;
}

2. dump hal層的資料

/hardware/qcom/audio/hal/audio_hw.c#out_write

static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,size_t bytes)
{
    struct stream_out *out = (struct stream_out *)stream;
    struct audio_device *adev = out->dev;
    ssize_t ret = 0;
    ......
    } else {
        if (out->pcm) {
            if (out->muted)
                memset((void *)buffer, 0, bytes);

            ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
        //JaychouNote: dump hal data begin.
    int tmpFd = open("/data/misc/audio/dumpTrack_hal.pcm", O_CREAT | O_WRONLY | O_APPEND, 0777);

    if ( tmpFd < 0 ) {
        ALOGE("Fail to open dumpTrack_hal file");
    } else {
        write(tmpFd, buffer, bytes);
        close(tmpFd);
    }
    //JaychouNote: dump hal data end.
            if (adev->adm_request_focus)
                adev->adm_request_focus(adev->adm_data, out->handle);

            if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
                ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
            }
            else
                ret = pcm_write(out->pcm, (void *)buffer, bytes);

            if (ret == 0)
                out->written += bytes / (out->config.channels * sizeof(short));

            if (adev->adm_abandon_focus)
                adev->adm_abandon_focus(adev->adm_data, out->handle);
        }
    }

exit:
    pthread_mutex_unlock(&out->lock);

    if (ret != 0) {
        if (out->pcm)
            ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
        out_standby(&out->stream.common);
        usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
               out_get_sample_rate(&out->stream.common));
    }
    return bytes;
}

3. 用Audacity分析dump出來的資料
用Audacity來聽dump出來的資料. 這裡聽hal的資料:
這裡寫圖片描述

這裡聽到是正常的話, 就說明是DSP的問題了, 如果有問題, 說明雜音在AP層就出現了.
這裡聽到Hal層的資料是正常的,所以就要往驅動層去分析了。

用QXDM抓取log, 再用QCAT解析, 發現0x1531的資料聽到了雜音, 也就是在 DSP的ADM出了問題。
這裡寫圖片描述

相關文章