All of lore.kernel.org
 help / color / mirror / Atom feed
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;

  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.