sound patch for pop & crackles

Mathew Kanner mat at cnd.mcgill.ca
Wed Nov 12 10:38:53 PST 2003


Hello All,
	Could people experiencing pops and crackles try the attached
patch and set hw.snd.fragps=128.   This patch also fixes select on
vchans.

more details in

http://www.freebsd.org/cgi/query-pr.cgi?pr=59208

	Thanks,
	--Mat

-- 
	I don't even know what street Canada is on.
			- Al Capone
-------------- next part --------------
--- channel.c.old	Wed Nov 12 02:42:43 2003
+++ channel.c	Wed Nov 12 03:59:31 2003
@@ -41,6 +41,10 @@
 #define DEB(x) x
 */
 
+static int chn_fragsps = 0;
+SYSCTL_INT(_hw_snd, OID_AUTO, fragsps, CTLFLAG_RW,
+	&chn_fragsps, 1, "max fragments per second, 0 to disable");
+
 static int chn_targetirqrate = 32;
 TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate);
 
@@ -59,7 +63,7 @@
 	return err;
 }
 SYSCTL_PROC(_hw_snd, OID_AUTO, targetirqrate, CTLTYPE_INT | CTLFLAG_RW,
-	0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", "");
+	0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", "default fragment targets this IRQ rate");
 static int report_soft_formats = 1;
 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
 	&report_soft_formats, 1, "report software-emulated formats");
@@ -113,10 +117,17 @@
 chn_wakeup(struct pcm_channel *c)
 {
     	struct snd_dbuf *bs = c->bufsoft;
+        struct pcmchan_children *pce;
 
-	CHN_LOCKASSERT(c);
-	if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
-		selwakeup(sndbuf_getsel(bs));
+//	CHN_LOCKASSERT(c);
+	if (SLIST_EMPTY(&c->children)) {
+		if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
+			selwakeup(sndbuf_getsel(bs));
+	} else {
+		SLIST_FOREACH(pce, &c->children, link) {
+			chn_wakeup(pce->channel);
+		}
+	}
 	wakeup(bs);
 }
 
@@ -931,7 +942,7 @@
 {
 	struct snd_dbuf *b = c->bufhard;
 	struct snd_dbuf *bs = c->bufsoft;
-	int bufsz, irqhz, tmp, ret;
+	int irqhz, tmp, ret;
 
 	CHN_LOCKASSERT(c);
 	if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED))
@@ -960,14 +971,23 @@
 			DEB(printf("%s: updating (%d, %d)\n", __func__, blkcnt, blksz));
 		}
 	} else {
+		if ( chn_fragsps != 0 && 
+			sndbuf_getbps(bs) * sndbuf_getspd(bs) / blksz > chn_fragsps) 
+		{
+			blksz = sndbuf_getbps(bs) * sndbuf_getspd(bs) / chn_fragsps;
+			tmp = 32;
+			while (tmp < blksz)
+				tmp <<= 1;
+			blksz = tmp;
+			if (blksz * blkcnt > CHN_2NDBUFMAXSIZE)
+				blkcnt = CHN_2NDBUFMAXSIZE / blksz;
+		}
 		ret = EINVAL;
 		if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE))
 			goto out;
 		ret = 0;
 		c->flags |= CHN_F_HAS_SIZE;
 	}
-
-	bufsz = blkcnt * blksz;
 
 	ret = sndbuf_remalloc(bs, blkcnt, blksz);
 	if (ret)


More information about the freebsd-current mailing list