alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* hardware not asking for more data using asyn call back
@ 2007-05-28 19:32 Ashlesha Shintre
  2007-05-28 22:43 ` stan
  0 siblings, 1 reply; 6+ messages in thread
From: Ashlesha Shintre @ 2007-05-28 19:32 UTC (permalink / raw)
  To: alsa-devel

Hi,

In my asynchronous playback program, the hardware stops asking for any data
and the program gets stuck after one call to the callback function.  I have
pasted the program below -- please let me know if something is wrong -

Thanks,
Ashlesha.

/* Reading wav file into a buffer and then trying to play it */
>
> #include <stdio.h>
> #include </usr/include/alsa/asoundlib.h>
> #include </usr/include/alsa/pcm.h>
> #include <sys/types.h>
> #include <unistd.h>
> #include <fcntl.h>
>
> #define SIZE 128
>
> short int *buffer;
> int ind=10, fd1;
> static snd_pcm_t *handle;
> static char *device = "default";                        /* playback device
> */
> snd_output_t *output = NULL;
> static short int *wto, *rfrom, buflen;
>
> void MyCallback(snd_async_handler_t *pcm_callback);
>
> int main()
> {
>     int i,j,n,length,count,a,err,k=0;
>     char c;
>     snd_pcm_sframes_t frames;
>     snd_async_handler_t *pcm_callback;
>
>
>
>     if((fd1=open("SA2.WAV",O_RDONLY,0))==-1)
>         printf("error opening wav file\n");
>
>     count=0;
>     while(count++<40)
>         a=read(fd1,&c,sizeof(char));
>
>     a=read(fd1,&length,sizeof(int));
>
>     n=length/SIZE;
>
>     printf("length = %d\n",length);
>
>     buflen = 4*SIZE;
>     buffer = (short int *) malloc (buflen*sizeof(short int));
>
>     wto = NULL;
>     rfrom = &buffer[0];
>
>     count=0;
>     a=1;
>     while(count<buflen && a>0)
>         a=read(fd1,&buffer[count++],sizeof(short int));
>     if(a<0)
>         printf("error in reading from wav file\n");
>
>     if((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) <
> 0) {
>         printf("error opening device: %s\n",snd_strerror(err));
>         return -1;
>     }
>
>     if((err = snd_pcm_set_params(handle,
>                                 SND_PCM_FORMAT_S16_LE,
>                                 SND_PCM_ACCESS_RW_INTERLEAVED,
>                                 1,
>                                 16000,
>                                 1,
>                                 1000)) < 0) {   /* 2 sec */
>             printf("Playback open error: %s\n", snd_strerror(err));
>             return -2;
>     }
>     printf("n=%d\n",n);
>     for (i=0; i<50; i++)
>     {
>         printf("i=%d\n",i);
>         frames = snd_pcm_writei(handle, rfrom, SIZE);
>         if(frames < 0)              // underrun
>             {
>                 printf("underrun recovery\n");
>                 frames = snd_pcm_recover(handle, frames,0);
>                 if(frames < 0){
>                     printf("error in recovery\n");
>                     return -3;
>                     }
>             }
>         if(frames >0 && frames < SIZE)
>             printf("expected to write %d, wrote %d\n",SIZE,frames);
>         printf("distance between ptrs before reinit is %d\n",rfrom - wto);
>         if(rfrom < &buffer[buflen-1])
>             {
>                 wto = rfrom;
>                 rfrom = rfrom + SIZE;
>             }
>         else
>             {
>                 printf("rfm at the end, rfrom -buffer[buflen-1]
> =%d\n",(*rfrom - buffer[buflen-1]));
>                 wto = rfrom;
>                 rfrom = &buffer[0];
>             }
>         for(k=0; k<SIZE; k++)
>             {
>                 a=read(fd1,(wto+k),sizeof(short int));
>                 if(a<0)
>                     printf("error in reading from wav file k = %d\n");
>             }
>         printf("buffer[i*SIZE] - rfrom = %d\n",(buffer[(i+1)*SIZE] -
> *rfrom));
>
>     }
>
>     /* Async Handler */
>
>    // err =
> snd_async_add_pcm_handler(&pcm_callback,handle,MyCallback,buffer);
>     err = snd_async_add_pcm_handler(&pcm_callback,handle,MyCallback,NULL);
>     if(err<0)
>         printf("add pcm handler error = %d\n%s\n",err,snd_strerror(err));
>
>     err = snd_pcm_start(handle);
>     if(err<0)
>         printf("error in starting snd pcm start err
> :%s\n",snd_strerror(err));
>
>    while (1) {
>                  if(wto == NULL)
>                     break;
>                  sleep(1);
>          }
>
>     err = snd_pcm_close(handle);
>     if(err<0)
>         printf("error in closing pcm device: %s\n",snd_strerror(err));
>     close(fd1);
>     return 0;
> }
>
> void MyCallback(snd_async_handler_t *pcm_callback)
> {
>
>     snd_pcm_t *pcm_handle = snd_async_handler_get_pcm(pcm_callback);
>     snd_pcm_sframes_t avail;
>     int count,a;
>     snd_pcm_uframes_t period_size = 64;
>     snd_pcm_sframes_t frames;
>     //short int *bufferin =
> snd_async_handler_get_callback_private(pcm_callback);
>
>     while((avail=snd_pcm_avail_update(pcm_handle)) >= period_size)
>         {
>             printf("available frames = %d\n",avail);
>             frames = snd_pcm_writei(pcm_handle, rfrom, SIZE);
>             if(frames < 0)              // underrun
>             {
>                 printf("underrun recovery\n");
>                 frames = snd_pcm_prepare(pcm_handle);
>                 printf("error from snd_pcm_prepare is: %d\n",frames);
>                 if(frames < 0){
>                     printf("error in recovery\n");
>                    // break;
>                     }
>             }
>
>             if(frames >0 && frames < SIZE)
>                 printf("expected to write %d, wrote %d\n",SIZE,frames);
>             count = 0;
>             a=1;
>             while(count<SIZE && a>0){
>                 a=read(fd1,(wto+count),sizeof(short int));      //write to
> the buffer from file
>                 ++count;
>                 }
>             printf("count = %d\n",count);
>             if(a <0){ //EOF
>                     wto = NULL;
>                     printf("end of file reached\n");
>                     break;
>                     }
>             else{
>                     if(rfrom < &buffer[buflen-1])
>                         {
>                             wto = wto+count;
>                             rfrom = rfrom + SIZE;
>                         }
>                     else
>                         {
>                             wto = wto + count;
>                             rfrom = &buffer[0];
>                         }                 //location of where to start
> writing from next
>                 }
>             ++ind;
>         }
>
>         printf("going out of callback, ind = %d\n",ind);
> }
>
>
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: hardware not asking for more data using asyn call back
  2007-05-28 19:32 hardware not asking for more data using asyn call back Ashlesha Shintre
@ 2007-05-28 22:43 ` stan
  0 siblings, 0 replies; 6+ messages in thread
From: stan @ 2007-05-28 22:43 UTC (permalink / raw)
  To: alsa-devel

On Mon, 28 May 2007 15:32:16 -0400
"Ashlesha Shintre" <ashlesha.shintre@gmail.com> wrote:

> Hi,
> 
> In my asynchronous playback program, the hardware stops asking for
> any data and the program gets stuck after one call to the callback
> function.  I have pasted the program below -- please let me know if
> something is wrong -
> 
> Thanks,
> Ashlesha.
> 
> /* Reading wav file into a buffer and then trying to play it */
> >
> > #include <stdio.h>
> > #include </usr/include/alsa/asoundlib.h>
> > #include </usr/include/alsa/pcm.h>
> > #include <sys/types.h>
> > #include <unistd.h>
> > #include <fcntl.h>
> >
> > #define SIZE 128
> >
> > short int *buffer;
> > int ind=10, fd1;
> > static snd_pcm_t *handle;
> > static char *device = "default";                        /* playback
> > device */
> > snd_output_t *output = NULL;
> > static short int *wto, *rfrom, buflen;
> >
> > void MyCallback(snd_async_handler_t *pcm_callback);
> >
> > int main()
> > {
> >     int i,j,n,length,count,a,err,k=0;
> >     char c;
> >     snd_pcm_sframes_t frames;
> >     snd_async_handler_t *pcm_callback;
> >
> >
> >
> >     if((fd1=open("SA2.WAV",O_RDONLY,0))==-1)
> >         printf("error opening wav file\n");
> >
> >     count=0;
> >     while(count++<40)
> >         a=read(fd1,&c,sizeof(char));
> >
> >     a=read(fd1,&length,sizeof(int));
> >
> >     n=length/SIZE;
> >
> >     printf("length = %d\n",length);
> >
> >     buflen = 4*SIZE;
> >     buffer = (short int *) malloc (buflen*sizeof(short int));
> >
> >     wto = NULL;
> >     rfrom = &buffer[0];
> >
> >     count=0;
> >     a=1;
> >     while(count<buflen && a>0)
> >         a=read(fd1,&buffer[count++],sizeof(short int));
> >     if(a<0)
> >         printf("error in reading from wav file\n");
> >
> >     if((err = snd_pcm_open(&handle, device,
> > SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
> >         printf("error opening device: %s\n",snd_strerror(err));
> >         return -1;
> >     }
> >
> >     if((err = snd_pcm_set_params(handle,
> >                                 SND_PCM_FORMAT_S16_LE,
> >                                 SND_PCM_ACCESS_RW_INTERLEAVED,
> >                                 1,
> >                                 16000,
> >                                 1,
> >                                 1000)) < 0) {   /* 2 sec */
> >             printf("Playback open error: %s\n", snd_strerror(err));
> >             return -2;
> >     }
> >     printf("n=%d\n",n);
> >     for (i=0; i<50; i++)
> >     {
> >         printf("i=%d\n",i);
> >         frames = snd_pcm_writei(handle, rfrom, SIZE);
> >         if(frames < 0)              // underrun
> >             {
> >                 printf("underrun recovery\n");
> >                 frames = snd_pcm_recover(handle, frames,0);
> >                 if(frames < 0){
> >                     printf("error in recovery\n");
> >                     return -3;
> >                     }
> >             }
> >         if(frames >0 && frames < SIZE)
> >             printf("expected to write %d, wrote %d\n",SIZE,frames);
> >         printf("distance between ptrs before reinit is %d\n",rfrom
> > - wto); if(rfrom < &buffer[buflen-1])
> >             {
> >                 wto = rfrom;
> >                 rfrom = rfrom + SIZE;
> >             }
> >         else
> >             {
> >                 printf("rfm at the end, rfrom -buffer[buflen-1]
> > =%d\n",(*rfrom - buffer[buflen-1]));
> >                 wto = rfrom;
> >                 rfrom = &buffer[0];
> >             }
> >         for(k=0; k<SIZE; k++)
> >             {
> >                 a=read(fd1,(wto+k),sizeof(short int));
> >                 if(a<0)
> >                     printf("error in reading from wav file k =
> > %d\n"); }
> >         printf("buffer[i*SIZE] - rfrom = %d\n",(buffer[(i+1)*SIZE] -
> > *rfrom));
> >
> >     }
> >
> >     /* Async Handler */
> >
> >    // err =
> > snd_async_add_pcm_handler(&pcm_callback,handle,MyCallback,buffer);
> >     err =
> > snd_async_add_pcm_handler(&pcm_callback,handle,MyCallback,NULL);
> > if(err<0) printf("add pcm handler error =
> > %d\n%s\n",err,snd_strerror(err));
> >
> >     err = snd_pcm_start(handle);
> >     if(err<0)
> >         printf("error in starting snd pcm start err
> > :%s\n",snd_strerror(err));
> >
> >    while (1) {
> >                  if(wto == NULL)
> >                     break;
> >                  sleep(1);

I think you should be filling the buffer in this loop instead of in the
callback function below.

> >          }
> >
> >     err = snd_pcm_close(handle);
> >     if(err<0)
> >         printf("error in closing pcm device:
> > %s\n",snd_strerror(err)); close(fd1);
> >     return 0;
> > }
> >
> > void MyCallback(snd_async_handler_t *pcm_callback)
> > {
> >
> >     snd_pcm_t *pcm_handle = snd_async_handler_get_pcm(pcm_callback);
> >     snd_pcm_sframes_t avail;
> >     int count,a;
> >     snd_pcm_uframes_t period_size = 64;
> >     snd_pcm_sframes_t frames;
> >     //short int *bufferin =
> > snd_async_handler_get_callback_private(pcm_callback);
> >
> >     while((avail=snd_pcm_avail_update(pcm_handle)) >= period_size)
> >         {
> >             printf("available frames = %d\n",avail);
> >             frames = snd_pcm_writei(pcm_handle, rfrom, SIZE);
> >             if(frames < 0)              // underrun
> >             {
> >                 printf("underrun recovery\n");
> >                 frames = snd_pcm_prepare(pcm_handle);
> >                 printf("error from snd_pcm_prepare is:
> > %d\n",frames); if(frames < 0){
> >                     printf("error in recovery\n");
> >                    // break;
> >                     }
> >             }
> >
> >             if(frames >0 && frames < SIZE)
> >                 printf("expected to write %d, wrote
> > %d\n",SIZE,frames); count = 0;
> >             a=1;
> >             while(count<SIZE && a>0){
> >                 a=read(fd1,(wto+count),sizeof(short
> > int));      //write to the buffer from file
> >                 ++count;
> >                 }
> >             printf("count = %d\n",count);
> >             if(a <0){ //EOF
> >                     wto = NULL;
> >                     printf("end of file reached\n");
> >                     break;
> >                     }
> >             else{
> >                     if(rfrom < &buffer[buflen-1])
> >                         {
> >                             wto = wto+count;
> >                             rfrom = rfrom + SIZE;
> >                         }
> >                     else
> >                         {
> >                             wto = wto + count;
> >                             rfrom = &buffer[0];
> >                         }                 //location of where to
> > start writing from next
> >                 }
> >             ++ind;
> >         }
> >
> >         printf("going out of callback, ind = %d\n",ind);
> > }
> >
> >
> >
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

Could you post the output of all the printfs when the program runs, and
describe the behavior.  I read what you read above as saying that it
hangs.  The printf output will indicate where it is hanging.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: hardware not asking for more data using asyn call back
@ 2007-05-29 19:19 Ashlesha Shintre
  2007-05-29 20:20 ` stan
  0 siblings, 1 reply; 6+ messages in thread
From: Ashlesha Shintre @ 2007-05-29 19:19 UTC (permalink / raw)
  To: stanl, alsa-devel

Hi,

Thanks Stan, for your response - Instead of copying pcm data from a wav
file, i decided to copy all the data to a master buffer first and then see
if the circular buffer implementation works -

so now instead of copying from the wave file, i m copying data from the
master buffer to the circular buffer.. however, as per your suggestion, if i
copy the data in the while loop in main, then, it might not always be copied
between 2 consecutive callbacks, but maybe more, as the callbacks are
asynchronous.

however, the hardware still does not ask for more data after executing the
callback function about twice -- is there a way to flush the hardware buffer
before beginning playback? I have pasted my code below

Regards,
Ashlesha.

/* Reading wav file into a buffer and then trying to play it */
>
> #include <stdio.h>
> #include </usr/include/alsa/asoundlib.h>
> #include </usr/include/alsa/pcm.h>
> #include <sys/types.h>
> #include <unistd.h>
> #include <fcntl.h>
>
> #define SIZE 128
> //mpos is the position in the master buffer to write from
> short int *buffer, *mbuf, *mpos;
> int ind=10, fd1, length;
> static snd_pcm_t *handle;
> static char *device = "default";                        /* playback device
> */
> snd_output_t *output = NULL;
> static short int *wto, *rfrom, buflen;
>
> void MyCallback(snd_async_handler_t *pcm_callback);
>
> int main()
> {
>     int i,j,n,count,a,err,k=0;
>     char c;
>     snd_pcm_sframes_t frames;
>     snd_async_handler_t *pcm_callback;
>
>
>
>     if((fd1=open("SA2.WAV",O_RDONLY,0))==-1)
>         printf("error opening wav file\n");
>
>     count=0;
>     while(count++<40)
>         a=read(fd1,&c,sizeof(char));
>
>     a=read(fd1,&length,sizeof(int));
>
>     n=length/SIZE;
>
>     printf("length = %d\n",length);
>     mbuf = (short int *) malloc (length * sizeof(short int));
>     mpos = &mbuf[0];
>
>     buflen = 4*SIZE;
>     buffer = (short int *) malloc (buflen*sizeof(short int));
>
>     wto = NULL;
>     rfrom = &buffer[0];
>
>     /* reading to master buffer */
>     count=0;
>     a=1;
>     while(count<length && a>0)
>         a=read(fd1,&mbuf[count++],sizeof(short int));
>     if(a<0){
>         printf("error in reading from wav file\n");
>         exit(1);
>         }
>     close (fd1);
>
>     for(count =0; count < buflen; count++)
>     {
>         buffer[count]=mbuf[count];
>     }
>     /******************************/
>
>     /*ALSA DEV INIT*/
>     if((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) <
> 0) {
>         printf("error opening device: %s\n",snd_strerror(err));
>         return -1;
>     }
>
>     if((err = snd_pcm_set_params(handle,
>                                 SND_PCM_FORMAT_S16_LE,
>                                 SND_PCM_ACCESS_RW_INTERLEAVED,
>                                 1,
>                                 16000,
>                                 1,
>                                 1000)) < 0) {   /* 2 sec */
>             printf("Playback open error: %s\n", snd_strerror(err));
>             return -2;
>     }
>     /*****************************/
>
>     printf("n=%d\n",n);
>     for (i=0; i<50; i++)
>     {
>         printf("i=%d\n",i);
>         frames = snd_pcm_writei(handle, rfrom, SIZE);
>         if(frames < 0)              // underrun
>             {
>                 printf("underrun recovery\n");
>                 frames = snd_pcm_recover(handle, frames,0);
>                 if(frames < 0){
>                     printf("error in recovery\n");
>                     return -3;
>                     }
>             }
>         if(frames >0 && frames < SIZE)
>             printf("expected to write %d, wrote %d\n",SIZE,frames);
>
>         printf("distance between ptrs before reinit is %d\n",rfrom - wto);
>         if(rfrom < &buffer[buflen-1])
>             {
>                 wto = rfrom;
>                 rfrom = rfrom + SIZE;
>             }
>         if(rfrom >= &buffer[buflen-1])
>             {
>                 printf("rfm at the end, rfrom -buffer[buflen-1]
> =%d\n",(*rfrom - buffer[buflen-1]));
>                 //wto = rfrom;
>                 rfrom = &buffer[0];
>             }
>
>         if((a = writetobuf())<0)
>                 printf("error in reading from wav file k = %d\n");
>
>         printf("buffer[i*SIZE] - rfrom = %d\n",(buffer[(i+1)*SIZE] -
> *rfrom));
>
>     }
>
>     /* Async Handler */
>
>
>     err = snd_async_add_pcm_handler(&pcm_callback,handle,MyCallback,NULL);
>     if(err<0)
>         printf("add pcm handler error = %d\n%s\n",err,snd_strerror(err));
>
>     err = snd_pcm_start(handle);
>     if(err<0)
>         printf("error in starting snd pcm start err
> :%s\n",snd_strerror(err));
>    /******************************/
>
>    while (1) {
>
>                  if(wto == NULL)
>                     break;      // redundancy -- already checking for this
> condition in MyCallback
>                  printf("infinite loop\n");
>                  sleep(1);
>          }
>
>     err = snd_pcm_close(handle);
>     if(err<0)
>         printf("error in closing pcm device: %s\n",snd_strerror(err));
>
>     return 0;
> }
>
> void MyCallback(snd_async_handler_t *pcm_callback)
> {
>
>     snd_pcm_t *pcm_handle = snd_async_handler_get_pcm(pcm_callback);
>     snd_pcm_sframes_t avail;
>     int count,a;
>     snd_pcm_uframes_t period_size = 64;
>     snd_pcm_sframes_t frames;
>
>     if((avail=snd_pcm_avail_update(pcm_handle)) >= period_size)
>         {
>             printf("available frames = %d\n",avail);
>             frames = snd_pcm_writei(pcm_handle, rfrom, SIZE);
>             if(frames < 0)              // underrun
>             {
>                 printf("underrun recovery\n");
>                 frames = snd_pcm_prepare(pcm_handle);
>                 printf("error from snd_pcm_prepare is: %d\n",frames);
>                 if(frames < 0){
>                     printf("error in recovery\n");
>
>                     }
>             }
>
>             if(frames >0 && frames < SIZE)
>                 printf("expected to write %d, wrote %d\n",SIZE,frames);
>
>
>             if(rfrom < &buffer[buflen-1])
>                 {
>                     wto = rfrom;
>                     rfrom = rfrom + SIZE;
>                 }
>             if(rfrom >= &buffer[buflen-1])
>                 {
> //                    wto = rfrom;
>                     rfrom = &buffer[0];
>                 }                 //location of where to start writing
> from next
>
>             if(writetobuf()<0){
>                 wto=NULL;
>                 exit(0); // returns 0 to the operating system -- so it
> ends the program!
>                 }
>             ++ind;
>         }
>
>         printf("going out of callback, ind = %d\n",ind);
> }
>
> /*Function to copy data from master buffer (mbuf) to circular buffer
> (buffer)*/
> int writetobuf()
> {
>     int count=-1;
>
>     while((++count < SIZE) && (mpos < &mbuf[length]))
>         *(mpos++) = *(wto+count);
>
>     if(mpos >= &mbuf[length-1])
>         return -1;
>     else
>         return 0;
> }
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: hardware not asking for more data using asyn call back
  2007-05-29 19:19 Ashlesha Shintre
@ 2007-05-29 20:20 ` stan
  2007-05-29 21:46   ` Ashlesha Shintre
  0 siblings, 1 reply; 6+ messages in thread
From: stan @ 2007-05-29 20:20 UTC (permalink / raw)
  To: alsa-devel

On Tue, 29 May 2007 15:19:12 -0400
"Ashlesha Shintre" <ashlesha.shintre@gmail.com> wrote:

> Hi,
> 
> Thanks Stan, for your response - Instead of copying pcm data from a
> wav file, i decided to copy all the data to a master buffer first and
> then see if the circular buffer implementation works -
> 
Not really necessary to use an intermediate buffer, but won't hurt.
I'm not sure why you are using a circular buffer, though it shouldn't
hurt either.

> so now instead of copying from the wave file, i m copying data from
> the master buffer to the circular buffer.. however, as per your
> suggestion, if i copy the data in the while loop in main, then, it
> might not always be copied between 2 consecutive callbacks, but maybe
> more, as the callbacks are asynchronous.

Well, your computer is creating the data that the callback function is
going to send to alsa.  If the callback function can fill the buffer
and send it to alsa and keep up with the play rate, then if you fill
the buffer in your main routine it will work even better.  Your program
is sleeping instead of doing anything.  You can put in place some kind
of interprocess communication so that they don't tread on each other in
the buffer.  With any modern processor that isn't heavily loaded, I
don't think this will matter anyway.

> 
> however, the hardware still does not ask for more data after
> executing the callback function about twice -- is there a way to
> flush the hardware buffer before beginning playback? I have pasted my
> code below
> 

The program output would still be helpful.  I implemented this a few
years ago.  I'll go look at the code and see how it differs from
yours.  I seem to recall that there was a sample of exactly this on the
alsa website, www.alsa-project.org.  You could look at that and it
might trigger an Aha! moment.

> Regards,
> Ashlesha.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: hardware not asking for more data using asyn call back
  2007-05-29 20:20 ` stan
@ 2007-05-29 21:46   ` Ashlesha Shintre
  0 siblings, 0 replies; 6+ messages in thread
From: Ashlesha Shintre @ 2007-05-29 21:46 UTC (permalink / raw)
  To: stan; +Cc: alsa-devel

> Not really necessary to use an intermediate buffer, but won't hurt.
> I'm not sure why you are using a circular buffer, though it shouldn't
> hurt either.


I wrote another code sometime back, to asychcronously playback data from a
wav file, where I copied the contents of the wav file to a master buffer
(like in this code) and then pumped data to the callback till the end of the
buffer was reached.  This code works fine -- I m trying to get the circular
buffer to work now as part of an application I am writing that will allow
realtime communication over the network between two hosts.

A circular buffer thus seems like a good idea, as in the case of real time
communication I wont really know how much data is going to come through the
network.

> so now instead of copying from the wave file, i m copying data from
> > the master buffer to the circular buffer.. however, as per your
> > suggestion, if i copy the data in the while loop in main, then, it
> > might not always be copied between 2 consecutive callbacks, but maybe
> > more, as the callbacks are asynchronous.
>
> Well, your computer is creating the data that the callback function is
> going to send to alsa.  If the callback function can fill the buffer
> and send it to alsa and keep up with the play rate, then if you fill
> the buffer in your main routine it will work even better.  Your program
> is sleeping instead of doing anything.  You can put in place some kind
> of interprocess communication so that they don't tread on each other in
> the buffer.  With any modern processor that isn't heavily loaded, I
> don't think this will matter anyway.


One question I had about this  interprocess communication was whether we can
pass more data to the callback function apart from the pcm handler.  From
what I can see in the ALSA libraries, the snd_async_add_pcm_handler function
only allows you to pass one parameter in the form of void * private_data.

> however, the hardware still does not ask for more data after
> > executing the callback function about twice -- is there a way to
> > flush the hardware buffer before beginning playback? I have pasted my
> > code below
>
>
> The program output would still be helpful.  I implemented this a few
> years ago.  I'll go look at the code and see how it differs from
> yours.  I seem to recall that there was a sample of exactly this on the
> alsa website, www.alsa-project.org.  You could look at that and it
> might trigger an Aha! moment.


I think you re talking about the pcm.c which implements asynchronous
playback which in my case works -- but it doesnt implement a circular
buffer.
Another query that I have regarding this is that I get a "Bad File
Descriptor" error from the snd_pcm_start function, but my asynchronous
playback code works despite  this error -- I dont think thats the reason for
this code failing, but its a mystry all the same!


Here is the output of my program:

i=49
> > error in starting snd pcm start err :File descriptor in bad state
> > infinite loop
> > inside callback, available frames = 364
> > going out of callback, ind = 1
> > infinite loop
> > inside callback, available frames = 577
> > going out of callback, ind = 2
> > infinite loop
> > inside callback, available frames = 790
> > underrun recovery
> > error from snd_pcm_prepare is: 0
> > going out of callback, ind = 3
> > infinite loop
> > infinite loop
> > infinite loop
> >
> > Regards,
Ashlesha.

>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: hardware not asking for more data using asyn call back
@ 2007-05-30  3:39 stan
  0 siblings, 0 replies; 6+ messages in thread
From: stan @ 2007-05-30  3:39 UTC (permalink / raw)
  To: alsa-devel

Somehow I replied to the wrong message and it went to a personal email
address. Putting it on the list so searches can find it  (for what that
is worth :-) )

Begin forwarded message:

Date: Tue, 29 May 2007 18:18:22 -0700
From: stan <stanl@cox.net>
To: "Ashlesha Shintre" <ashlesha.shintre@gmail.com>
Subject: Re: hardware not asking for more data using asyn call back


On Tue, 29 May 2007 15:19:12 -0400
"Ashlesha Shintre" <ashlesha.shintre@gmail.com> wrote:

<snip>

I didn't understand what you were asking before.  It sounds to me like
you want to have a thread running that accepts input from arbitrary
processes and puts it in the main buffer.  Then when the alsa callback
occurs you want to take any new sound samples and send them to alsa.
If that is the case, it makes more sense for the main buffer to be
the circular buffer and the alsa buffer to be just a regular buffer.
That's just personal preference though.

As far as the handle error, I don't know what it means beyond what it
says.  You would have to look in the sources for the alsa library to
see what causes that error to be generated.  

I don't see anything wrong in the logic of the code below, but the
output indicates that you are not keeping up with the play rate.  This
is astonishing.  At each play you can see that the available room in
the buffer grows larger until larger than 1000, the buffer you have
allocated.  I'm not sure what infinite loop means and how your program
is recovering from it.  I presume that is where the time is being eaten
up that isn't allowing you to keep up with the requests for data.

I don't think you need to check if there is room when you get a
callback.  You should be able to just write the data to alsa using the
writei call.  i.e. eliminate the snd_pcm_avail_update call.

I'm not familiar enough with alsa to help you further.  Perhaps someone
else can give you a hint or point you to the right place to look.

> 
> /* Reading wav file into a buffer and then trying to play it */
> >
> > #include <stdio.h>
> > #include </usr/include/alsa/asoundlib.h>
> > #include </usr/include/alsa/pcm.h>
> > #include <sys/types.h>
> > #include <unistd.h>
> > #include <fcntl.h>
> >
> > #define SIZE 128
> > //mpos is the position in the master buffer to write from
> > short int *buffer, *mbuf, *mpos;
> > int ind=10, fd1, length;
> > static snd_pcm_t *handle;
> > static char *device = "default";                        /* playback
> > device */
> > snd_output_t *output = NULL;
> > static short int *wto, *rfrom, buflen;
> >
> > void MyCallback(snd_async_handler_t *pcm_callback);
> >
> > int main()
> > {
> >     int i,j,n,count,a,err,k=0;
> >     char c;
> >     snd_pcm_sframes_t frames;
> >     snd_async_handler_t *pcm_callback;
> >
> >
> >
> >     if((fd1=open("SA2.WAV",O_RDONLY,0))==-1)
> >         printf("error opening wav file\n");
> >
> >     count=0;
> >     while(count++<40)
> >         a=read(fd1,&c,sizeof(char));
> >
> >     a=read(fd1,&length,sizeof(int));
> >
> >     n=length/SIZE;
> >
> >     printf("length = %d\n",length);
> >     mbuf = (short int *) malloc (length * sizeof(short int));
> >     mpos = &mbuf[0];
> >
> >     buflen = 4*SIZE;
> >     buffer = (short int *) malloc (buflen*sizeof(short int));
> >
> >     wto = NULL;
> >     rfrom = &buffer[0];
> >
> >     /* reading to master buffer */
> >     count=0;
> >     a=1;
> >     while(count<length && a>0)
> >         a=read(fd1,&mbuf[count++],sizeof(short int));
> >     if(a<0){
> >         printf("error in reading from wav file\n");
> >         exit(1);
> >         }
> >     close (fd1);
> >
> >     for(count =0; count < buflen; count++)
> >     {
> >         buffer[count]=mbuf[count];
> >     }
> >     /******************************/
> >
> >     /*ALSA DEV INIT*/
> >     if((err = snd_pcm_open(&handle, device,
> > SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
> >         printf("error opening device: %s\n",snd_strerror(err));
> >         return -1;
> >     }
> >
> >     if((err = snd_pcm_set_params(handle,
> >                                 SND_PCM_FORMAT_S16_LE,
> >                                 SND_PCM_ACCESS_RW_INTERLEAVED,
> >                                 1,
> >                                 16000,
> >                                 1,
> >                                 1000)) < 0) {   /* 2 sec */
> >             printf("Playback open error: %s\n", snd_strerror(err));
> >             return -2;
> >     }
> >     /*****************************/
> >
> >     printf("n=%d\n",n);
> >     for (i=0; i<50; i++)
> >     {
> >         printf("i=%d\n",i);
> >         frames = snd_pcm_writei(handle, rfrom, SIZE);
> >         if(frames < 0)              // underrun
> >             {
> >                 printf("underrun recovery\n");
> >                 frames = snd_pcm_recover(handle, frames,0);
> >                 if(frames < 0){
> >                     printf("error in recovery\n");
> >                     return -3;
> >                     }
> >             }
> >         if(frames >0 && frames < SIZE)
> >             printf("expected to write %d, wrote %d\n",SIZE,frames);
> >
> >         printf("distance between ptrs before reinit is %d\n",rfrom
> > - wto); if(rfrom < &buffer[buflen-1])
> >             {
> >                 wto = rfrom;
> >                 rfrom = rfrom + SIZE;
> >             }
> >         if(rfrom >= &buffer[buflen-1])
> >             {
> >                 printf("rfm at the end, rfrom -buffer[buflen-1]
> > =%d\n",(*rfrom - buffer[buflen-1]));
> >                 //wto = rfrom;
> >                 rfrom = &buffer[0];
> >             }
> >
> >         if((a = writetobuf())<0)
> >                 printf("error in reading from wav file k = %d\n");
> >
> >         printf("buffer[i*SIZE] - rfrom = %d\n",(buffer[(i+1)*SIZE] -
> > *rfrom));
> >
> >     }
> >
> >     /* Async Handler */
> >
> >
> >     err =
> > snd_async_add_pcm_handler(&pcm_callback,handle,MyCallback,NULL);
> > if(err<0) printf("add pcm handler error =
> > %d\n%s\n",err,snd_strerror(err));
> >
> >     err = snd_pcm_start(handle);
> >     if(err<0)
> >         printf("error in starting snd pcm start err
> > :%s\n",snd_strerror(err));
> >    /******************************/
> >
> >    while (1) {
> >
> >                  if(wto == NULL)
> >                     break;      // redundancy -- already checking
> > for this condition in MyCallback
> >                  printf("infinite loop\n");
> >                  sleep(1);
> >          }
> >
> >     err = snd_pcm_close(handle);
> >     if(err<0)
> >         printf("error in closing pcm device:
> > %s\n",snd_strerror(err));
> >
> >     return 0;
> > }
> >
> > void MyCallback(snd_async_handler_t *pcm_callback)
> > {
> >
> >     snd_pcm_t *pcm_handle = snd_async_handler_get_pcm(pcm_callback);
> >     snd_pcm_sframes_t avail;
> >     int count,a;
> >     snd_pcm_uframes_t period_size = 64;
> >     snd_pcm_sframes_t frames;
> >
> >     if((avail=snd_pcm_avail_update(pcm_handle)) >= period_size)
                             ^  
>From the alsa lib api docs.  |  
                             |  
Using of this function is useless for the standard read/write
operations. Use it only for mmap access. See to snd_pcm_delay.

Obtain delay for a running PCM handle.

Parameters:
    	pcm 	PCM handle
    	delayp 	Returned delay in frames

Returns:
    0 on success otherwise a negative error code

Delay is distance between current application frame position and sound
frame position. It's positive and less than buffer size in normal
situation, negative on playback underrun and greater than buffer size
on capture overrun.

> >         {
> >             printf("available frames = %d\n",avail);
> >             frames = snd_pcm_writei(pcm_handle, rfrom, SIZE);
Using rfrom is going to be problematic if you get to a 

> >             if(frames < 0)              // underrun
> >             {
> >                 printf("underrun recovery\n");
> >                 frames = snd_pcm_prepare(pcm_handle);
> >                 printf("error from snd_pcm_prepare is:
> > %d\n",frames); if(frames < 0){
> >                     printf("error in recovery\n");
> >
> >                     }
> >             }
> >
> >             if(frames >0 && frames < SIZE)
> >                 printf("expected to write %d, wrote
> > %d\n",SIZE,frames);
> >
> >
> >             if(rfrom < &buffer[buflen-1])
> >                 {
> >                     wto = rfrom;
> >                     rfrom = rfrom + SIZE;
> >                 }
> >             if(rfrom >= &buffer[buflen-1])
> >                 {
> > //                    wto = rfrom;
> >                     rfrom = &buffer[0];
> >                 }                 //location of where to start
> > writing from next
> >
> >             if(writetobuf()<0){
> >                 wto=NULL;
> >                 exit(0); // returns 0 to the operating system -- so
> > it ends the program!
> >                 }
> >             ++ind;
> >         }
> >
> >         printf("going out of callback, ind = %d\n",ind);
> > }
> >
> > /*Function to copy data from master buffer (mbuf) to circular buffer
> > (buffer)*/
> > int writetobuf()
> > {
> >     int count=-1;
> >
> >     while((++count < SIZE) && (mpos < &mbuf[length]))
> >         *(mpos++) = *(wto+count);
> >
> >     if(mpos >= &mbuf[length-1])
> >         return -1;
> >     else
> >         return 0;
> > }
> >

i=49
error in starting snd pcm start err :File descriptor in bad state
infinite loop
inside callback, available frames = 364
going out of callback, ind = 1
infinite loop
inside callback, available frames = 577
going out of callback, ind = 2
infinite loop
inside callback, available frames = 790
underrun recovery
error from snd_pcm_prepare is: 0
going out of callback, ind = 3
infinite loop
infinite loop
infinite loop

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-05-30  3:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-28 19:32 hardware not asking for more data using asyn call back Ashlesha Shintre
2007-05-28 22:43 ` stan
  -- strict thread matches above, loose matches on Subject: below --
2007-05-29 19:19 Ashlesha Shintre
2007-05-29 20:20 ` stan
2007-05-29 21:46   ` Ashlesha Shintre
2007-05-30  3:39 stan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).