snd_pcm_playback_silence

1 silence size的设置

在snd_pcm_hw_params时设置,设置的目的时防止读旧数据,出现nosie,只有playback才需要

capture不需要,因为capture data都是充足的,只会出现读数据慢的情况,不会读到旧数据。

silence size的设置有一定的要求:

static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
                 struct snd_pcm_sw_params *params)
{
    struct snd_pcm_runtime *runtime;
    int err;

    ...
    if (params->avail_min == 0)
        return -EINVAL;
    if (params->silence_size >= runtime->boundary) {
        if (params->silence_threshold != 0)
            return -EINVAL;
    } else {
        if (params->silence_size > params->silence_threshold)
            return -EINVAL;
        if (params->silence_threshold > runtime->buffer_size)
            return -EINVAL;
    }
...

一共有两个地方会call snd_pcm_playback_silence

一个snd_pcm_update_hw_ptr0,

另一个时初始化过程 snd_pcm_start:

static void snd_pcm_post_start(struct snd_pcm_substream *substream,
                   snd_pcm_state_t state)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    snd_pcm_trigger_tstamp(substream);
    runtime->hw_ptr_jiffies = jiffies;
    runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / 
                                runtime->rate;
    runtime->status->state = state;
    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
        runtime->silence_size > 0)
        snd_pcm_playback_silence(substream, ULONG_MAX);//第二个实参为ULONG
    snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART);
}

 2 snd_pcm_playback_silence

 有两个逻辑

逻辑1:

if (runtime->silence_size < runtime->boundary)

清的时app_ptr之后的旧数据,size为设置的silenc_size?

如果runtime->silence_filled >= runtime->buffer_size),表示dma data充足,无需清旧数据。否则数据不足,就清旧数据

逻辑2:

是else flow

是清old hw_ptr和new hw_ptr之间的数据,就是旧数据。

void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    snd_pcm_uframes_t frames, ofs, transfer;
    int err;

    if (runtime->silence_size < runtime->boundary) {
        snd_pcm_sframes_t noise_dist, n;
        snd_pcm_uframes_t appl_ptr = READ_ONCE(runtime->control->appl_ptr);
        if (runtime->silence_start != appl_ptr) {
            n = appl_ptr - runtime->silence_start;
            if (n < 0)
                n += runtime->boundary;
            if ((snd_pcm_uframes_t)n < runtime->silence_filled)
                runtime->silence_filled -= n;
            else
                runtime->silence_filled = 0;
            runtime->silence_start = appl_ptr;
        }
        if (runtime->silence_filled >= runtime->buffer_size)//表示dma data充足,无需清旧数据,否则就清旧数据
            return;
        noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
        if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold)
            return;
        frames = runtime->silence_threshold - noise_dist;
        if (frames > runtime->silence_size)
            frames = runtime->silence_size;
    } else {
        if (new_hw_ptr == ULONG_MAX) {    /* initialization */ //初始化时走的flow,snd_pcm_start call的
            snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
            if (avail > runtime->buffer_size)
                avail = runtime->buffer_size;
            runtime->silence_filled = avail > 0 ? avail : 0;
            runtime->silence_start = (runtime->status->hw_ptr +
                          runtime->silence_filled) %
                         runtime->boundary;
        } else {//非出初始化走的flow
            ofs = runtime->status->hw_ptr;
            frames = new_hw_ptr - ofs;
            if ((snd_pcm_sframes_t)frames < 0)
                frames += runtime->boundary;
            runtime->silence_filled -= frames;
            if ((snd_pcm_sframes_t)runtime->silence_filled < 0) {
                runtime->silence_filled = 0;
                runtime->silence_start = new_hw_ptr;
            } else {
                runtime->silence_start = ofs;
            }
        }
        frames = runtime->buffer_size - runtime->silence_filled;
    }
    if (snd_BUG_ON(frames > runtime->buffer_size))
        return;
    if (frames == 0)
        return;
    ofs = runtime->silence_start % runtime->buffer_size;
    while (frames > 0) {
        transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
        err = fill_silence_frames(substream, ofs, transfer);//填0清旧数据
        snd_BUG_ON(err < 0);
        runtime->silence_filled += transfer;
        frames -= transfer;
        ofs = 0;
    }
}

 

posted @ 2025-05-28 21:53  Action_er  阅读(37)  评论(0)    收藏  举报