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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox