code: plan9front

Download patch

ref: 027f579f43cdc908bf8d51c27bdf5da8e7773940
parent: 571d3258ef7e0db436c2ad4dbd79244e6d319e8f
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Mar 27 19:47:45 EDT 2024

nusb/audio: pick a different rate if 44.1kHz is not available

Try to pick the closest (but higher) rate. If there are none,
pick a lower one.

Mixfs is able to convert to whichever rate, so this should
make plenty of new audio devices work.

--- a/sys/src/cmd/nusb/audio/audio.c
+++ b/sys/src/cmd/nusb/audio/audio.c
@@ -360,12 +360,19 @@
 }
 
 Dev*
-setupep(Dev *d, Iface *ac, Ep *e, int speed)
+setupep(Dev *d, Iface *ac, Ep *e, int *speed, int force)
 {
 	int dir = e->dir;
-	Aconf *c;
+	Aconf *c, *bestc;
 	Range *f;
+	Ep *beste;
+	int closest, sp;
 
+	bestc = nil;
+	beste = nil;
+	closest = 1<<30;
+	sp = *speed;
+
 	for(;e != nil; e = e->next){
 		c = e->iface->aux;
 		if(c == nil || e != c->ep || e->dir != dir)
@@ -372,21 +379,39 @@
 			continue;
 		if(c->format != 1 || c->bits != audiores || 8*c->bps != audiores || c->channels != audiochan)
 			continue;
-		for(f = c->freq; f != c->freq+c->nfreq; f++)
-			if(speed >= f->min && speed <= f->max)
+		for(f = c->freq; f != c->freq+c->nfreq; f++){
+			if(sp >= f->min && sp <= f->max)
 				goto Foundaltc;
+			if(force)
+				continue;
+			if(f->min >= sp && closest-sp >= f->min-sp){
+				closest = f->min;
+				bestc = c;
+				beste = e;
+			}else if(bestc == nil || (f->max < sp && closest < sp && sp-closest > sp-f->max)){
+				closest = f->max;
+				bestc = c;
+				beste = e;
+			}
+		}
 	}
-	werrstr("no altc found");
-	return nil;
+	if(bestc == nil){
+		werrstr("no altc found");
+		return nil;
+	}
+	e = beste;
+	c = bestc;
+	sp = closest;
 
 Foundaltc:
-	if(setalt(d, e->iface) < 0)
+	if(setalt(d, e->iface) < 0){
+		fprint(2, "setalt: %r\n");
 		return nil;
-	if(setclock(d, ac, c, speed) < 0){
+	}
+	if(setclock(d, ac, c, sp) < 0){
 		werrstr("setclock: %r");
 		return nil;
 	}
-
 	if((d = openep(d, e)) == nil){
 		werrstr("openep: %r");
 		return nil;
@@ -393,11 +418,9 @@
 	}
 	devctl(d, "samplesz %d", audiochan*audiores/8);
 	devctl(d, "sampledelay %d", audiodelay);
-	devctl(d, "hz %d", speed);
-	if(e->dir==Ein)
-		devctl(d, "name audioinU%s", audiodev->hname);
-	else
-		devctl(d, "name audioU%s", audiodev->hname);	
+	devctl(d, "hz %d", sp);
+	devctl(d, "name audio%sU%s", e->dir==Ein ? "in" : "", audiodev->hname);
+	*speed = sp;
 	return d;
 }
 
@@ -430,15 +453,15 @@
 
 		speed = atoi(f[1]);
 Setup:
-		if((d = setupep(audiodev, audiocontrol, audioepout, speed)) == nil){
+		if((d = setupep(audiodev, audiocontrol, audioepout, &speed, 1)) == nil){
 			responderror(r);
 			return;
 		}
+		audiofreq = speed;
 		closedev(d);
 		if(audioepin != nil)
-			if(d = setupep(audiodev, audiocontrol, audioepin, speed))
+			if(d = setupep(audiodev, audiocontrol, audioepin, &speed, 1))
 				closedev(d);
-		audiofreq = speed;
 	} else if(strcmp(f[0], "delay") == 0){
 		audiodelay = atoi(f[1]);
 		speed = audiofreq;
@@ -534,7 +557,7 @@
 			audioepout = e;
 			break;
 		}
-		if((ed = setupep(d, ac, e, audiofreq)) == nil){
+		if((ed = setupep(d, ac, e, &audiofreq, 0)) == nil){
 			fprint(2, "setupep: %r\n");
 
 			if(e == audioepin)