ALSA: Способы предотвращения опустошения для динамика

Я воспроизводю одноканальный звук в режиме без чередования. Когда я записываю аудиоданные в динамик, у меня происходит отключение: ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred

Вот как я пишу:

    printf("%d",snd_pcm_avail (spkhandle));  
    ret = snd_pcm_writen(spkhandle, pSpeakerBuf , framesIn18Millisec);
    if(ret < 0)
    {
        snd_pcm_recover(spkhandle, ret, 0);
    }

Каковы различные способы/конфигурации параметров для предотвращения запуска ALSA?

(Я использую Linux 3.0, ARM)

Изменить: вот измерение буфера с использованием API snd_pcm_avail()

      snd_pcm_avail = 2304      << snd_pcm_writen call 1 success
      snd_pcm_avail = 2160      << snd_pcm_writen call 2 success
      snd_pcm_avail = 2016      << snd_pcm_writen call 3 success
      snd_pcm_writen error -32 Broken pipe  << snd_pcm_writen call 4 failure
      ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred  << And displays this message

Вот результат, который запросил Марко:

snd_output_t* out;
....
// Do alsa parameters init .... 
....
snd_output_stdio_attach(&out, stderr, 0);
snd_pcm_dump_sw_setup(spkhandle, out);

  tstamp_mode  : NONE
  period_step  : 1
  avail_min    : 144
  period_event : 0
  start_threshold  : 288
  stop_threshold   : 2304
  silence_threshold: 0
  silence_size : 0
  boundary     : 1207959552

person Lunar Mushrooms    schedule 30.01.2013    source источник
comment
Имеет ли ваш поток приоритет планирования в реальном времени?   -  person marko    schedule 30.01.2013
comment
@Marko, да, я установил приоритет планирования в реальном времени - SCHED_FIFO.   -  person Lunar Mushrooms    schedule 30.01.2013
comment
Каков ваш буферный период относительного периода уведомления?   -  person marko    schedule 30.01.2013
comment
Я новичок в альсе. Я пишу звук длительностью 18 миллисекунд в одноканальный динамик (поскольку моя собственная встроенная система требует 18 мс). Как видно из вопроса, snd_pcm_avail уменьшается на 144 байта. Как этого избежать?   -  person Lunar Mushrooms    schedule 30.01.2013
comment
Вы ожидаете, что доступное место для семплов в буфере уменьшится после записи в него, но скорее более чем на 144 кадра за 18 мс. Не могли бы вы поместить вызов snd_pcm_dump_sw_setup() в свой код где-нибудь перед тем, как начнется звук, и поделиться с нами выводом консоли?   -  person marko    schedule 30.01.2013
comment
@Marko: обновлен вопрос с выводом snd_pcm_dump_sw_setup().   -  person Lunar Mushrooms    schedule 30.01.2013
comment
В соответствии с комментарием @Marko, какова ваша частота дискретизации и значение framesIn18Millisec. Обратите внимание, что для звука CD-качества (частота дискретизации 44 100 Гц) должно быть 793,8 сэмпла за 18 мс. Хотя для частоты дискретизации 8 кГц было бы достаточно 144 семплов...   -  person twalberg    schedule 30.01.2013
comment
@twalberg Действительно так. Здесь стоит отметить, что многие вызовы alsa_pcm_sw_param_* и alsa_pcm_hw_param_* являются «максимальными усилиями» — и вы не всегда получаете то, что хотите. Установка частоты дискретизации является одним из них. После установки параметров всегда имеет смысл проверить, что вы на самом деле получили.   -  person marko    schedule 30.01.2013


Ответы (2)


Я предполагаю, что этот код работает в жестком цикле и предназначен для блокировки на snd_pcm_writen(). Частота дискретизации не указана; Я предполагаю 48 кГц, так как все числа хорошо делятся.

Я думаю, что здесь происходит следующее:

  • snd_pcm_write() не гарантирует записи всех предоставленных кадров (возвращаемое значение всегда проверяется только на наличие ошибок). Судя по журналу snd_pcm_avail(), на самом деле он потребляет avail_min или 144 кадров на каждый. Это 3 мс звука.
  • Предполагая, что звук в этот момент не работает, после двух записей количество кадров в буфере равно start_threshold — при 288 выборках; аудиовыход начинается
  • вызовы блока printf(), и я, кажется, помню, что snd_pcm_avail() должен синхронизироваться с аппаратным обеспечением вывода звука и также может блокироваться. Поскольку теперь вы опережаете воспроизведение на 6 мс, вполне возможно, что буфер пуст во время третьего вызова snd_pcm_writen().

Таким образом, на данный момент вам не следует вызывать printf(), и вам, вероятно, нужно компенсировать тот факт, что snd_pcm_writen() не использует все кадры в pSpeakerBuf.

person marko    schedule 30.01.2013
comment
спасибо за советы. Мне это помогло. Кстати, настоящей причиной опустошения в моем случае был неисправный драйвер alsa (кастомные изменения). - person Lunar Mushrooms; 31.01.2013
comment
Извините, как вы это получили и как вы обновили драйвер alsa? - person Roman; 22.11.2017

Это опустошение буфера. Вы можете попробовать увеличить размер буфера, явно указав его в файле ~/.asoundrc?

person Rahul    schedule 30.01.2013
comment
Опустошение буфера означает, что буфер становится пустым, а не полным. Больший буфер либо не повлияет на симптомы, либо даже усугубит их... - person twalberg; 30.01.2013