ALSA: débordement de tampon sur snd_pcm_writei appel

J'obtiens les erreurs de tampon lors de l'exécution d'un vieux programme, j'ai récemment ramenés de ses cendres.

Le programme des charges jusqu'à un son brut de fichier entièrement en mémoire (2100 octets de long, 525 cadres) et prépare ALSA pour la sortie (44.1 khz, 2 canaux, signé de 16 bits):

if ((err = snd_pcm_set_params(audio_handle,
                              SND_PCM_FORMAT_S16_LE,
                              SND_PCM_ACCESS_RW_INTERLEAVED,
                              2,
                              44100,
                              1,
                              sound.playback_us)) < 0) {
  printf("E: Failed to prepare PCM: %s\n", snd_strerror(err));
  return -1;
}

PCM état est PREPARED avant la première lecture du son. Son joue correctement la première fois, cependant, la deuxième fois qu'il est joué, l'état est RUNNING et un -EPIPE ("Broken pipe") est lancée par snd_pcm_writei. La lecture de la logique:

frames = snd_pcm_writei(audio_handle,
                        sound.data,
                        write_size);

if(frames < 0) {
  printf("E: %s: attempting to recover\n", snd_strerror(frames));
  frames = snd_pcm_recover(audio_handle, frames, 0);

  if(frames < 0) {
    printf("E: snd_pcm_writei failed\n");
    break;
  }
} else if(frames > 0 && frames < write_size)
  printf("E: Short write (expected %li, wrote %li)\n", write_size, frames);
else
  printf("wrote %li frames\n", frames);

Étrangement, elle joue correctement à la troisième fois, à défaut, une fois encore, l'heure suivante. En d'autres termes, il échoue avec une -EPIPE d'erreur à chaque fois.

Par souci de simplicité, je suis en train de jouer les sons à 1 seconde d'intervalle.

Quel est le problème avec la logique ci-dessus?


Code mis à jour pour utiliser la nouvelle API ALSA; peut être trouvé à: http://paste.ubuntu.com/7257181/


MODIFIER

Viens de découvrir que si l'on fait des tests pour un -EPIPE état et re-prépare le PCM poignée avant de re-délivrance de la snd_pcm_writei appel, tout est bon. Mon (nouveau) la question est donc... pourquoi?

if(frames == -EPIPE) {
  snd_pcm_prepare(pcm.handle);
  frames = snd_pcm_writei(pcm.handle,
                          sound.data, //sound.data + (offset << 1),
                          write_size);
}

OriginalL'auteur miguelg | 2014-04-15