艾莎异步回放(Alsa Asynchronous Playback)

2019-10-18 19:27发布

我想玩采用异步播放方式的文件。 我写了下面的代码,但它不工作,它是深藏不露。 任何帮助在此先感谢。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <poll.h>
#include <alsa/asoundlib.h>

snd_pcm_t *playback_handle;
short buf[1024];
snd_pcm_uframes_t period_size = 64;



void playback_callback (snd_async_handler_t *pcm_callback)
{
    int err;
  //      snd_pcm_t *playback_handle = snd_async_handler_get_pcm(pcm_callback);
    void *private_data = snd_async_handler_get_callback_private(pcm_callback);
    FILE *fp = (FILE *)private_data;
    snd_pcm_sframes_t avail;
    if(feof(fp)){
            fclose(fp);
            snd_pcm_drain(playback_handle);
            snd_pcm_close(playback_handle);
            exit(2);
    }
    avail = snd_pcm_avail_update(playback_handle);
    printf("avil returned : %d\n",(int)avail);
    while (avail >= period_size) {
            fread(buf, 1, period_size, fp);
            snd_pcm_writei (playback_handle, buf, period_size);
            avail = snd_pcm_avail_update(playback_handle);
    }

}
int main (int argc, char *argv[])
{

    snd_pcm_hw_params_t *hw_params;
    snd_pcm_sw_params_t *sw_params;
    snd_pcm_sframes_t frames_to_deliver;
    int nfds,rate=48000;
    int err;
    struct pollfd *pfds;
#if 1
    FILE *fp=fopen("beep-fl.wav","rb");

    fseek(fp ,44, SEEK_SET);
#endif


  if ((err = snd_pcm_open (&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) <0)     {
         fprintf (stderr, "cannot open audio device %s (%s)\n",
                             "default",
             snd_strerror (err));
             exit (1);
    }

    if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
            fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
                             snd_strerror (err));
            exit (1);
    }

    if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
            fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
                     snd_strerror (err));
            exit (1);
    }

    if ((err =   snd_pcm_hw_params_set_access(playback_handle,hw_params,
     SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
            fprintf (stderr, "cannot set access type (%s)\n",
                     snd_strerror (err));

         exit (1);
    }

    if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
            fprintf (stderr, "cannot set sample format (%s)\n",
                     snd_strerror (err));
            exit (1);
    }

    if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, 0)) < 0) {
            fprintf (stderr, "cannot set sample rate (%s)\n",
                     snd_strerror (err));
            exit (1);
    }

    if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 1)) < 0) {
            fprintf (stderr, "cannot set channel count (%s)\n",
                     snd_strerror (err));
            exit (1);
    }

    snd_pcm_uframes_t buffer_size = 1024;

    snd_pcm_hw_params_set_buffer_size_near (playback_handle, hw_params, &buffer_size);
    snd_pcm_hw_params_set_period_size_near (playback_handle, hw_params, &period_size, 0 );


    if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
            fprintf (stderr, "cannot set parameters (%s)\n",
                     snd_strerror (err));
            exit (1);
    }

    snd_pcm_hw_params_free (hw_params);
if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
            fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
                     snd_strerror (err));
            exit (1);
    }
    if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0) {
            fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
                     snd_strerror (err));
            exit (1);
    }
    if ((err = snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, period_size)) < 0) {
            fprintf (stderr, "cannot set minimum available count (%s)\n",
                     snd_strerror (err));
            exit (1);
    }
    if ((err = snd_pcm_sw_params_set_start_threshold(playback_handle, sw_params, (buffer_size-period_size) )) < 0) {
            fprintf (stderr, "cannot set start mode (%s)\n",
                     snd_strerror (err));
            exit (1);
    }
    if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0) {
            fprintf (stderr, "cannot set software parameters (%s)\n",
                     snd_strerror (err));
            exit (1);
    }


    if ((err = snd_pcm_prepare (playback_handle)) < 0) {
            fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
                     snd_strerror (err));
            exit (1);
    }
    fread( buf , 1 , 2 * period_size , fp );
    snd_async_handler_t *pcm_callback;
    snd_async_add_pcm_handler(&pcm_callback, playback_handle, playback_callback, (void *)fp);


    snd_pcm_start(playback_handle);
    snd_pcm_writei (playback_handle, buf, 2 * period_size);

    sleep(10);

    fclose(fp);
    snd_pcm_drain (playback_handle);
    snd_pcm_close (playback_handle);
    exit (0);
}

对不起,我的代码格式化..

Answer 1:

异步回调使用的信号,其中有很多问题来实现:

  • 许多设备不支持这一点; 和
  • 你不能在回调中使用任何功能,除了那些从的异步信号安全函数列表 ; 和
  • 任何信号将中断sleep通话。

强烈建议从来没有使用异步回调。



文章来源: Alsa Asynchronous Playback
标签: alsa