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