2013-10-19 94 views
1

我想用異步播放方法播放文件。我寫了下面的代碼,但它不工作,它沒有顯示任何內容。任何幫助提前感謝。Alsa異步播放

#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); 
} 

對不起我的代碼格式化..

回答

1

異步回調使用的信號,其中有很多問題實現:

  • 許多設備不支持這一點;和
  • 您不能在回調中使用任何函數,除了那些來自list of async-signal-safe functions;和
  • 任何信號都會中斷sleep呼叫。

強烈建議不要使用異步回調。

+0

它工作時,我用一些繁忙的等待循環替換'睡眠(10)',但不能很好地播放(播放聲音有些緩慢) –