嵌入式软件工程师&&太极拳
全部博文(548)
分类:
2011-02-20 19:47:16
/* ALSA用户空间播放程序(基于"中断") */ #include#include #include #include #include snd_pcm_t *playback_handle; short buf[4096]; int playback_callback(snd_pcm_sframes_t nframes) { int err; printf("playback callback called with %u frames\n", nframes); /* 填充缓冲区 */ if((err = snd_pcm_writei(playback_handle, buf, nframes)) < 0) { fprintf(stderr, "write failed (%s)\n", snd_strerror(err)); } return err; } 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; int err; struct pollfd *pfds; if((err = snd_pcm_open(&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "cannot open audio device %s (%s)\n", argv[1], 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, 44100, 0)) < 0) { fprintf(stderr, "cannot set sample rate (%s)\n", snd_strerror(err)); exit(1); } if((err = snd_set_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); /* 告诉ALSA当4096个以上帧可以传递时唤醒我们 */ 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); } /* 设置4096帧传递一次数据 */ if((err = snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, 4096)) < 0) { fprintf(stderr, "cannot set minimun available count (%s)\n", snd_strerror(err)); exit(1); } /*一旦有数据就开始播放 */ if((err = snd_pcm_sw_params_set_start_threshold(playback_handle, sw_params, 0U)) < 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); } /* 每4096帧接口将中断内核,ALSA将很快唤醒本程序 */ if((err = snd_pcm_prepare(playback_handle)) < 0) { fprintf(stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror(err)); exit(1); } while(1) { /* 等待,直到接口准备好传递数据,或者1s超时发生 */ if((err = snd_pcm_wait(playback_handle, 1000)) < 0) { fprintf(stderr, "poll failed (%s)\n", snd_strerror(err)); break; } /* 查出有多少空间可放置playback数据 */ if((frames_to_deliver = snd_pcm_avail_update(playback_handle)) < 0) { if(frames_to_deliver == -EPIPE) { fprintf(stderr, "an xrun occured\n"); break; } else { fprintf(stderr, "unknown ALSA avail update return value (%d)\n", frames_to_deliver); break; } } frames_to_deliver = frames_to_deliver > 4096 ? 4096 : frames_to_deliver; /* 传递数据 */ if(playback_callback(frames_to_deliver) != frames_to_deliver) { fprintf(stderr, "playback callback failed\n"); break; } } snd_pcm_close(playback_handle); exit(0); return 0; }