From: Takashi Iwai <tiwai@suse.de>
To: Jack O'Quin <joq@io.com>
Cc: "Asbjørn Sæbø" <asbjs@stud.ntnu.no>, alsa-devel@lists.sourceforge.net
Subject: Re: Lowest latency: JACK, or ALSA directly?
Date: Wed, 17 Nov 2004 20:41:20 +0100 [thread overview]
Message-ID: <s5h4qjos1pb.wl@alsa2.suse.de> (raw)
In-Reply-To: <s5h6544s529.wl@alsa2.suse.de>
[-- Attachment #1: Type: text/plain, Size: 949 bytes --]
At Wed, 17 Nov 2004 19:28:46 +0100,
I wrote:
>
> With this model, basically the number of periods in the buffer doesn't
> mean the latency at all but is required just for the stream
> configuration. The required condition is only nperiods >= 2.
> So, this option isn't even necessary if we query the nearest buffer
> size to "f-val * period_size". Maybe this would be a better
> implementation from the perspective of usability.
Ok, the attached below is more radical change. The -f option is
removed and the semantics of -n option is changed. It means the
minimal playback latency requested by user.
The buffer size doesn't have to be exactly nperiods * period_size.
JACK accepts more periods returned from the driver than requested.
Also, the different number of periods are accepted, too, for playback
and capture directions.
Untested as usual :)
(BTW, the jack code is still based on the older ALSA API.
Is this intentional?)
Takashi
[-- Attachment #2: Type: text/plain, Size: 8768 bytes --]
--- jack-audio-connection-kit-0.99.0/drivers/alsa/alsa_driver.c-dist 2004-11-15 15:00:06.000000000 +0100
+++ jack-audio-connection-kit-0.99.0/drivers/alsa/alsa_driver.c 2004-11-17 20:34:42.623799183 +0100
@@ -325,6 +325,7 @@ alsa_driver_configure_stream (alsa_drive
snd_pcm_t *handle,
snd_pcm_hw_params_t *hw_params,
snd_pcm_sw_params_t *sw_params,
+ unsigned int *nperiodsp,
unsigned long *nchns,unsigned long sample_width)
{
int err, format;
@@ -436,13 +437,23 @@ alsa_driver_configure_stream (alsa_drive
return -1;
}
- if ((err = snd_pcm_hw_params_set_periods (handle, hw_params,
- driver->user_nperiods, 0))
+ *nperiodsp = driver->user_nperiods;
+ snd_pcm_hw_params_set_periods_min (handle, hw_params, nperiodsp, NULL);
+ *nperiodsp = driver->user_nperiods;
+ if ((*nperiodsp = snd_pcm_hw_params_set_periods_near (handle, hw_params,
+ *nperiodsp, NULL))
< 0) {
jack_error ("ALSA: cannot set number of periods to %u for %s",
- driver->user_nperiods, stream_name);
+ *nperiodsp, stream_name);
return -1;
}
+
+ if (*nperiodsp < driver->user_nperiods) {
+ jack_error ("ALSA: got smaller periods %u than %u for %s",
+ *nperiodsp, (unsigned int)driver->user_nperiods, stream_name);
+ return -1;
+ }
+ fprintf(stderr, "nperiods = %d for %s\n", *nperiodsp, stream_name);
if (!jack_power_of_two(driver->frames_per_cycle)) {
jack_error("JACK: frames must be a power of two "
@@ -451,12 +462,12 @@ alsa_driver_configure_stream (alsa_drive
}
if ((err = snd_pcm_hw_params_set_buffer_size (handle, hw_params,
- driver->user_nperiods *
+ *nperiodsp *
driver->frames_per_cycle))
< 0) {
jack_error ("ALSA: cannot set buffer length to %" PRIu32
" for %s",
- driver->user_nperiods * driver->frames_per_cycle,
+ *nperiodsp * driver->frames_per_cycle,
stream_name);
return -1;
}
@@ -475,7 +486,7 @@ alsa_driver_configure_stream (alsa_drive
return -1;
}
- stop_th = driver->user_nperiods * driver->frames_per_cycle;
+ stop_th = *nperiodsp * driver->frames_per_cycle;
if (driver->soft_mode) {
stop_th = (snd_pcm_uframes_t)-1;
}
@@ -496,20 +507,27 @@ alsa_driver_configure_stream (alsa_drive
#if 0
fprintf (stderr, "set silence size to %lu * %lu = %lu\n",
- driver->frames_per_cycle, driver->user_nperiods,
- driver->frames_per_cycle * driver->user_nperiods);
+ driver->frames_per_cycle, *nperiodsp,
+ driver->frames_per_cycle * *nperiodsp);
if ((err = snd_pcm_sw_params_set_silence_size (
handle, sw_params,
- driver->frames_per_cycle * driver->user_nperiods)) < 0) {
+ driver->frames_per_cycle * *nperiodsp)) < 0) {
jack_error ("ALSA: cannot set silence size for %s",
stream_name);
return -1;
}
#endif
- if ((err = snd_pcm_sw_params_set_avail_min (
- handle, sw_params, driver->frames_per_cycle)) < 0) {
+ if (handle == driver->playback_handle)
+ err = snd_pcm_sw_params_set_avail_min (
+ handle, sw_params,
+ driver->frames_per_cycle * (*nperiodsp - driver->user_nperiods + 1));
+ else
+ err = snd_pcm_sw_params_set_avail_min (
+ handle, sw_params, driver->frames_per_cycle);
+
+ if (err < 0) {
jack_error ("ALSA: cannot set avail min for %s", stream_name);
return -1;
}
@@ -532,8 +550,6 @@ alsa_driver_set_parameters (alsa_driver_
int dir;
unsigned int p_period_size = 0;
unsigned int c_period_size = 0;
- unsigned int p_nfragments = 0;
- unsigned int c_nfragments = 0;
channel_t chn;
unsigned int pr = 0;
unsigned int cr = 0;
@@ -554,6 +570,7 @@ alsa_driver_set_parameters (alsa_driver_
driver->capture_handle,
driver->capture_hw_params,
driver->capture_sw_params,
+ &driver->capture_nperiods,
&driver->capture_nchannels,
driver->capture_sample_bytes)) {
jack_error ("ALSA: cannot configure capture channel");
@@ -569,6 +586,7 @@ alsa_driver_set_parameters (alsa_driver_
driver->playback_handle,
driver->playback_hw_params,
driver->playback_sw_params,
+ &driver->playback_nperiods,
&driver->playback_nchannels,
driver->playback_sample_bytes)) {
jack_error ("ALSA: cannot configure playback channel");
@@ -623,9 +641,6 @@ alsa_driver_set_parameters (alsa_driver_
p_period_size =
snd_pcm_hw_params_get_period_size (
driver->playback_hw_params, &dir);
- p_nfragments =
- snd_pcm_hw_params_get_periods (
- driver->playback_hw_params, &dir);
driver->playback_sample_format = (snd_pcm_format_t)
snd_pcm_hw_params_get_format (
driver->playback_hw_params);
@@ -647,9 +662,6 @@ alsa_driver_set_parameters (alsa_driver_
c_period_size =
snd_pcm_hw_params_get_period_size (
driver->capture_hw_params, &dir);
- c_nfragments =
- snd_pcm_hw_params_get_periods (
- driver->capture_hw_params, &dir);
driver->capture_sample_format = (snd_pcm_format_t)
snd_pcm_hw_params_get_format (
driver->capture_hw_params);
@@ -667,26 +679,6 @@ alsa_driver_set_parameters (alsa_driver_
}
}
- if (driver->capture_handle && driver->playback_handle) {
- if (p_nfragments != c_nfragments) {
- jack_error ("alsa_pcm: different period counts for "
- "playback and capture!");
- return -1;
- }
-
- driver->nfragments = c_nfragments;
-
- } else if (driver->capture_handle) {
-
- driver->nfragments = c_nfragments;
-
- } else {
-
- driver->nfragments = p_nfragments;
-
- }
-
- driver->buffer_frames = driver->frames_per_cycle * driver->nfragments;
driver->playback_sample_bytes =
snd_pcm_format_physical_width (driver->playback_sample_format)
/ 8;
@@ -934,7 +926,7 @@ alsa_driver_start (alsa_driver_t *driver
pavail = snd_pcm_avail_update (driver->playback_handle);
- if (pavail != driver->buffer_frames) {
+ if (pavail != driver->frames_per_cycle * driver->playback_nperiods) {
jack_error ("ALSA: full buffer not available at start");
return -1;
}
@@ -955,11 +947,11 @@ alsa_driver_start (alsa_driver_t *driver
for (chn = 0; chn < driver->playback_nchannels; chn++) {
alsa_driver_silence_on_channel (driver, chn,
- driver->buffer_frames);
+ driver->user_nperiods * driver->frames_per_cycle);
}
snd_pcm_mmap_commit (driver->playback_handle, poffset,
- driver->buffer_frames);
+ driver->user_nperiods * driver->frames_per_cycle);
if ((err = snd_pcm_start (driver->playback_handle)) < 0) {
jack_error ("could not start playback (%s)",
@@ -1107,10 +1099,11 @@ alsa_driver_silence_untouched_channels (
jack_nframes_t nframes)
{
channel_t chn;
+ jack_nframes_t buffer_frames = driver->frames_per_cycle * driver->playback_nperiods;
for (chn = 0; chn < driver->playback_nchannels; chn++) {
if ((driver->channels_not_done & (1<<chn))) {
- if (driver->silent[chn] < driver->buffer_frames) {
+ if (driver->silent[chn] < buffer_frames) {
alsa_driver_silence_on_channel_no_mark (
driver, chn, nframes);
driver->silent[chn] += nframes;
@@ -1686,7 +1679,7 @@ alsa_driver_attach (alsa_driver_t *drive
* (external) latency
*/
jack_port_set_latency (port, driver->frames_per_cycle
- * driver->nfragments);
+ * driver->user_nperiods);
driver->playback_ports =
jack_slist_append (driver->playback_ports, port);
@@ -1901,7 +1894,6 @@ alsa_driver_new (char *name, char *playb
driver->ctl_handle = 0;
driver->hw = 0;
driver->capture_and_playback_not_synced = FALSE;
- driver->nfragments = 0;
driver->max_nchannels = 0;
driver->user_nchannels = 0;
driver->playback_nchannels = user_playback_nchnls;
--- jack-audio-connection-kit-0.99.0/drivers/alsa/alsa_driver.h-dist 2004-11-15 15:06:52.000000000 +0100
+++ jack-audio-connection-kit-0.99.0/drivers/alsa/alsa_driver.h 2004-11-17 20:34:46.671045579 +0100
@@ -84,14 +84,14 @@ typedef struct {
char *alsa_name_playback;
char *alsa_name_capture;
char *alsa_driver;
- snd_pcm_uframes_t buffer_frames;
unsigned long channels_not_done;
unsigned long channel_done_bits;
snd_pcm_format_t playback_sample_format;
snd_pcm_format_t capture_sample_format;
float max_sample_val;
unsigned long user_nperiods;
- unsigned long nfragments;
+ unsigned int playback_nperiods;
+ unsigned int capture_nperiods;
unsigned long last_mask;
snd_ctl_t *ctl_handle;
snd_pcm_t *playback_handle;
next prev parent reply other threads:[~2004-11-17 19:41 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-11-11 14:41 Lowest latency: JACK, or ALSA directly? Asbjørn Sæbø
2004-11-11 15:11 ` Jack O'Quin
2004-11-12 9:04 ` Asbjørn Sæbø
2004-11-12 16:42 ` Jack O'Quin
2004-11-12 17:01 ` Takashi Iwai
2004-11-12 17:19 ` Jack O'Quin
2004-11-17 14:55 ` Takashi Iwai
2004-11-17 17:32 ` Jack O'Quin
2004-11-17 18:28 ` Takashi Iwai
2004-11-17 19:41 ` Takashi Iwai [this message]
2004-11-18 2:07 ` Jack O'Quin
2004-11-18 12:38 ` Takashi Iwai
2004-11-11 15:34 ` Paul Davis
2004-11-12 9:11 ` Asbjørn Sæbø
2004-11-12 14:47 ` Gilles Degottex
2004-11-12 15:28 ` Giuliano Pochini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=s5h4qjos1pb.wl@alsa2.suse.de \
--to=tiwai@suse.de \
--cc=alsa-devel@lists.sourceforge.net \
--cc=asbjs@stud.ntnu.no \
--cc=joq@io.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.