Thanks
I am sorry for sending it here. I changed e-mails, it should be send
to linux-audio-dev mailing list.
-----------------------------------------------------------
Althought I wanted to write it for ALSA and tryed it a lot of times.
It do not work correctly as I wanted.  One big problem is good
documentation for ALSA (althought ALSA is nice :) ).

The documentation you writed - mini fullduplex is incomplete
and have a lot of wrongs (I send some corrects for mini capture and
playback before).

ALSA 0.9.0 HOWTO do not have enought information to write
mini full duplex application.

alsa-lib is api documentation and do not have practical advices to
write easy way mini full duplex aplication (or applications).

I do not have much time to research how to write it.
But I am look forward when the nice documentation will exist or I
will have much time to more try on it.

I send myfullduplex.cpp to Jaroslav before. But probably do not have
much time.

I get the fullduplex to work, but after while it do not work
and no sound was heard. So I do not know what happend,
althought I tryed catch some errors.

If you could look on it. To let me and all others know how looks the
minifullduplex application.

                               Pavel

----- PŮVODNÍ ZPRÁVA -----
Od: "Paul Davis" <[EMAIL PROTECTED]>
Komu: [EMAIL PROTECTED]
Předmět: Re: [Alsa-devel] Help with LATENCY FULL DUPLEX AUDIO 
Datum: 26.4.2002 - 0:31:59

> >I am just working (finishing) on modular realtime
> effect procesor. It >is my thesis project. I would like
> to ask three questions: >
> >1.
> >How can I calculate the latency in ms with OSS
> driver?

> this is alsa-devel. there is nobody here who is
> interested in supporting this archaic and limiting API.
> we would encourage you to convert your application to
> ALSA or ... (see below)

> >2.
> >My program do the effects on audio in realtime.
> >So I added recording the sound to hard disk.

> This is called creaping featuritis :)

> >This work ok. But when I play back the recorded sound
> (from HD), it >changes me buffer length that latency is
> very big. My solution to >this problem was to close
> device and
> >initalize same device one more time after playing the
> sound. >Is there better solution for me?

> Use JACK (http://jackit.sf.net) and forget about this
> stuff in your program, which can then focus on what it
> does best.

> Its also hard to understand what you've described,
> since the act of playing or capturing data does nothing
> to the h/w or s/w settings of the drivers, even under
> OSS AFAIK (and certainly not under ALSA).

> >3.
> >Is there some advices how to set the lowest latency?

> No 2.4-series kernel can go below about 128 frames per
> interrupt right now. For general advice on setting
> latency, see the somewhat incomplete docs at
> www.alsa-project.org. You might also read up on low
> latency issues at http://www.linuxdj.com/lad/

> --p
#include <alsa/asoundlib.h>
#include <unistd.h>

      main (int argc, char *argv[])
      {
           int i;
           short pbuf[440000];
           short cbuf[44000];
           int periodsize = 1600;
           int periods = 2;
           int rate = 48000;
           int channels = 2;
           snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
           snd_pcm_t *playback_handle;
           snd_pcm_t *capture_handle;
           snd_pcm_hw_params_t *hw_params;
           int err;
           if ((err = snd_pcm_open(&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 
0)) < 0) {
                 fprintf (stderr, "cannot open audio device %s\n", argv[1]);
                 exit (1);
           }

           if ((err = snd_pcm_open(&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 
0)) < 0) {
                 fprintf (stderr, "cannot open audio device %s\n", argv[1]);
                 exit (1);
           }

           snd_pcm_hw_params_malloc(&hw_params);

           snd_pcm_hw_params_any(playback_handle, hw_params);
           snd_pcm_hw_params_set_access(playback_handle, hw_params, 
SND_PCM_ACCESS_RW_INTERLEAVED);
           snd_pcm_hw_params_set_format(playback_handle, hw_params, format);
           snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, rate, 0);
           snd_pcm_hw_params_set_channels(playback_handle, hw_params, channels);
            /* Set number of periods. Periods used to be called fragments. */
           if (snd_pcm_hw_params_set_periods(playback_handle, hw_params, periods, 0) < 
0) {
                fprintf(stderr, "Error setting periods.\n");
                return(-1);
          }
           /* Set buffer size (in frames). The resulting latency is given by */
           /* latency = periodsize * periods / (rate * bytes_per_frame)     */
           if (snd_pcm_hw_params_set_buffer_size_near(playback_handle, hw_params, 
(periodsize * periods)>>2) < 0) {
                fprintf(stderr, "Error setting buffersize.\n");
                return(-1);
           }
           snd_pcm_hw_params(playback_handle, hw_params);
//           snd_pcm_hw_params_free(hw_params);

           snd_pcm_hw_params_any(capture_handle, hw_params);
           snd_pcm_hw_params_set_access(capture_handle, hw_params, 
SND_PCM_ACCESS_RW_INTERLEAVED);
           snd_pcm_hw_params_set_format(capture_handle, hw_params, format);
           snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, rate, 0);
           snd_pcm_hw_params_set_channels(capture_handle, hw_params, channels);
           snd_pcm_hw_params(capture_handle, hw_params);
           if (snd_pcm_hw_params_set_periods(capture_handle, hw_params, periods, 0) < 
0) {
                fprintf(stderr, "Error setting periods.\n");
                return(-1);
          }
           /* Set buffer size (in frames). The resulting latency is given by */
           /* latency = periodsize * periods / (rate * bytes_per_frame)     */
           if (snd_pcm_hw_params_set_buffer_size_near(capture_handle, hw_params, 
(periodsize * periods)>>2) < 0) {
                fprintf(stderr, "Error setting buffersize.\n");
                return(-1);
           }
           snd_pcm_hw_params_free(hw_params);

        int bytes_per_frame = channels * (snd_pcm_format_width(format) / 8);
        //float flatency = periodsize * periods / (rate * bytes_per_frame);
        float flatency = ((float) snd_pcm_hw_params_get_buffer_size(hw_params)) / 
(rate * bytes_per_frame);
        int latency = snd_pcm_hw_params_get_period_size(hw_params, NULL);
        //snd_pcm_hw_params_get_buffer_size(hw_params);// / (rate * bytes_per_frame);
        printf("Latency: %d %f\n", latency, flatency);

        if (snd_pcm_format_set_silence(format, pbuf, latency*channels) < 0) {
                        fprintf(stderr, "silence error\n");
                        exit(-1);
         }

           snd_pcm_prepare(playback_handle);
           snd_pcm_prepare(capture_handle);

         snd_pcm_writei(playback_handle, pbuf, latency);
         snd_pcm_writei(playback_handle, pbuf, latency);

        while(1) {
//                 printf("Capturing...\n");
                 err = snd_pcm_readi(capture_handle, cbuf, latency);
                 if (err == ESTRPIPE) printf("Pozastaveno\n");
                 if (err == EPIPE) printf("Overrun\n");
                 if (err == EBADFD) printf("PCM neni ve spravnem stavu\n");
//                 printf("Playback...\n");

                 for(int i = 0; i<(latency*channels); i++) pbuf[i] = cbuf[i];
                 err = snd_pcm_writei(playback_handle, pbuf, latency);//sizeof (pbuf)
                 if (err == ESTRPIPE) printf("Pozastaveno\n");
                 if (err == EPIPE) printf("Overrun\n");
                 if (err == EBADFD) printf("PCM neni ve spravnem stavu\n");
        }
           snd_pcm_close(playback_handle);
           snd_pcm_close(capture_handle);
           return 0;
     }

#include <alsa/asoundlib.h>
#include <unistd.h>

      main (int argc, char *argv[])
      {
           int i;
           short pbuf[440000];
           short cbuf[44000];
           int periodsize = 8048;
           int periods = 2;
           int rate = 44100;
           int channels = 2;
           snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
           snd_pcm_t *playback_handle;
           snd_pcm_t *capture_handle;
           snd_pcm_hw_params_t *hw_params;
           int err;
           if ((err = snd_pcm_open(&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 
0)) < 0) {
                 fprintf (stderr, "cannot open audio device %s\n", argv[1]);
                 exit (1);
           }

           if ((err = snd_pcm_open(&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 
0)) < 0) {
                 fprintf (stderr, "cannot open audio device %s\n", argv[1]);
                 exit (1);
           }

           snd_pcm_hw_params_malloc(&hw_params);

           snd_pcm_hw_params_any(playback_handle, hw_params);
           snd_pcm_hw_params_set_access(playback_handle, hw_params, 
SND_PCM_ACCESS_RW_INTERLEAVED);
           snd_pcm_hw_params_set_format(playback_handle, hw_params, format);
           snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, rate, 0);
           snd_pcm_hw_params_set_channels(playback_handle, hw_params, channels);
            /* Set number of periods. Periods used to be called fragments. */
           if (snd_pcm_hw_params_set_periods(playback_handle, hw_params, periods, 0) < 
0) {
                fprintf(stderr, "Error setting periods.\n");
                return(-1);
          }
           /* Set buffer size (in frames). The resulting latency is given by */
           /* latency = periodsize * periods / (rate * bytes_per_frame)     */
           if (snd_pcm_hw_params_set_buffer_size_near(playback_handle, hw_params, 
(periodsize * periods)>>2) < 0) {
                fprintf(stderr, "Error setting buffersize.\n");
                return(-1);
           }
           snd_pcm_hw_params(playback_handle, hw_params);
//           snd_pcm_hw_params_free(hw_params);

           snd_pcm_hw_params_any(capture_handle, hw_params);
           snd_pcm_hw_params_set_access(capture_handle, hw_params, 
SND_PCM_ACCESS_RW_INTERLEAVED);
           snd_pcm_hw_params_set_format(capture_handle, hw_params, format);
           snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, rate, 0);
           snd_pcm_hw_params_set_channels(capture_handle, hw_params, channels);
           snd_pcm_hw_params(capture_handle, hw_params);
           if (snd_pcm_hw_params_set_periods(capture_handle, hw_params, periods, 0) < 
0) {
                fprintf(stderr, "Error setting periods.\n");
                return(-1);
          }
           /* Set buffer size (in frames). The resulting latency is given by */
           /* latency = periodsize * periods / (rate * bytes_per_frame)     */
           if (snd_pcm_hw_params_set_buffer_size_near(capture_handle, hw_params, 
(periodsize * periods)>>2) < 0) {
                fprintf(stderr, "Error setting buffersize.\n");
                return(-1);
           }
           snd_pcm_hw_params_free(hw_params);

        int bytes_per_frame = channels * (snd_pcm_format_width(format) / 8);
        //float flatency = periodsize * periods / (rate * bytes_per_frame);
        float flatency = ((float) snd_pcm_hw_params_get_buffer_size(hw_params)) / 
(rate * bytes_per_frame);
        int latency = snd_pcm_hw_params_get_period_size(hw_params, NULL);
        //snd_pcm_hw_params_get_buffer_size(hw_params);// / (rate * bytes_per_frame);
        printf("Latency: %d %f\n", latency, flatency);

        if ((err = snd_pcm_prepare(playback_handle)) < 0) {
                printf("Prepare error: %s\n", snd_strerror(err));
                exit(-1);
        }
/*
        snd_pcm_dump(playback_handle, output);
        snd_pcm_dump(capoture_handle, output);
        fflush(stdout);
*/
         if ((err = snd_pcm_link(capture_handle, playback_handle)) < 0) {
                        printf("Streams link error: %s\n", snd_strerror(err));
                        exit(-1);
         }

        if (snd_pcm_format_set_silence(format, pbuf, latency*channels) < 0) {
                        fprintf(stderr, "silence error\n");
                        exit(-1);
         }

//           snd_pcm_prepare(playback_handle);
//           snd_pcm_prepare(capture_handle);

         snd_pcm_writei(playback_handle, pbuf, latency);
         snd_pcm_writei(playback_handle, pbuf, latency);

         if ((err = snd_pcm_start(capture_handle)) < 0) {
                        printf("Go error: %s\n", snd_strerror(err));
                        exit(-1);
         }

        while(1) {
//                 printf("Capturing...\n");
                 err = snd_pcm_readi(capture_handle, cbuf, latency);
                 if (err == ESTRPIPE) printf("Pozastaveno\n");
                 if (err == EPIPE) printf("Overrun\n");
                 if (err == EBADFD) printf("PCM neni ve spravnem stavu\n");
//                 printf("Playback...\n");

                 for(int i = 0; i<(latency*channels); i++) pbuf[i] = cbuf[i];
                 err = snd_pcm_writei(playback_handle, pbuf, latency);//sizeof (pbuf)
                 if (err == ESTRPIPE) printf("Pozastaveno\n");
                 if (err == EPIPE) printf("Overrun\n");
                 if (err == EBADFD) printf("PCM neni ve spravnem stavu\n");
        }
           snd_pcm_unlink(capture_handle);
           snd_pcm_close(playback_handle);
           snd_pcm_close(capture_handle);
           return 0;
     }

Reply via email to