Wednesday, August 26, 2015

Simple thing but difficult to find [ALSA wav file]


I was in need of ALSA and honestly, I'd just few testing style programming of it long before.

It need to take wav file as input and do a playback of that file using ALSA. However, I need to learn it form scratch, though to find any suitable example according how I can handle wav file to send as ALSA PCM playback, was difficult.

So I wish to write some explanation of it here, and will try to exclude those what you can find and learn by a short googling.

Below part, I presume you already know, or if you don't, I found -

http://www.linuxjournal.com/article/6735?page=0,0

         is the best and most informative.


 if((err = snd_pcm_open(&pcm_handle,"plughw:0,0",SND_PCM_STREAM_PLAYBACK,0)) < 0)  
   {  
     fprintf(stderr,"Can't open the sound device %s",snd_strerror(err));  
     return err;  
   }  
   // setting parameters for ALSA  
   snd_pcm_hw_params_alloca(&params);  
   snd_pcm_hw_params_any(pcm_handle,params);  
   snd_pcm_hw_params_set_access(pcm_handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);  
   snd_pcm_hw_params_set_format(pcm_handle,params,SND_PCM_FORMAT_S16_LE);  
   snd_pcm_hw_params_set_channels(pcm_handle,params,1);  
   snd_pcm_hw_params_set_rate_near(pcm_handle,params,&rate,NULL);  
   if((err = snd_pcm_hw_params(pcm_handle,params)) < 0)  
   {  
     fprintf(stderr,"Can't set parameters for sound %s\n",snd_strerror(err));  
     return err;  
   }  

Later the issue is in-front. How to let ALSA to read from my file pointer.

yes, declare a file pointer, and open a wav file with it as readonly.

 afile = fopen(afilename, "r");  


read a chunk of the opened file, and assign it in a character array.

I've done it as ->

 while ((nread = fread(buf, sizeof(short), 128, afile)) > 0)  
           {  
                if((err = snd_pcm_writei(pcm_handle, buf, nread)) != nread)  
                {  
                     fprintf(stderr,"Failed to write audio %s", snd_strerror(err));  
                     snd_pcm_prepare(pcm_handle);  
                }  
           }  

where in buf, I'm keeping the read 2 byte long 128 data elements using function fread(),

By using snd_pcm_writei(), I send the data [buf] to PCM device.

And at last, snd_pcm_prepare(), to let the stream ready to write data on stream again, which actually avoid the underrun.

So, that's it. A full file could be found here.


No comments:

Post a Comment