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