On Fri, 2012-11-30 at 09:59 +0100, David Henningsson wrote:
> Hi,
> 
> I'm researching a bug where some set of USB speakers stopped working, 
> probably in 2.x. The peculiar thing about this sound card is that seems 
> to only work at a sample rate of 46875 Hz.
> 
> So in 2.x, the probe fails with
> "E: [pulseaudio] alsa-sink.c: Failed to find any supported sample 
> rates.", whereas in an earlier version, it would just happily work at 
> 46875 Hz instead, as I understand it.
> 
> So my first question is; why do we check all these rates, when we end up 
> just alternating between default-sample-rate (44100 Hz) and 
> alternate-sample-rate (48000 Hz) anyway?
> And second, can we try not to fail if we can't find any supported sample 
> rates, so we can fix this regression?
> 
> For reference, this is the bug (with pulse verbose logs in it):
> 
> https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/1074783

This was added by:

commit e67440e2208fb8182916493b57b75e91013510e7
Author: Arun Raghavan <[email protected]>
Date:   Mon Oct 17 22:46:06 2011 +0530

    alsa: Probe sink/source sample rates
    
    This probes sink and source sample rates and uses this information to
    validate rate changes and check incoming passthrough formats.

So yes, this is a regression. I'm attaching a patch that should fix
this.

-- Arun
>From 43053b4580c9fab9d73035f2511bbe49ed5feebb Mon Sep 17 00:00:00 2001
From: Arun Raghavan <[email protected]>
Date: Mon, 3 Dec 2012 11:27:27 +0530
Subject: [PATCH] alsa: Try to support non-standard rates in alsa-sink/source

We inadvertantly stopped supporting non-standard rates when the
passthrough work was done. This makes sure that if no standard rates are
supported, we try to fallback to whatever ALSA gives us.
---
 src/modules/alsa/alsa-sink.c   |  2 +-
 src/modules/alsa/alsa-source.c |  2 +-
 src/modules/alsa/alsa-util.c   | 28 +++++++++++++++++++---------
 src/modules/alsa/alsa-util.h   |  2 +-
 4 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index ee82ec7..ed41b22 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -2202,7 +2202,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     if (is_iec958(u) || is_hdmi(u))
         set_formats = TRUE;
 
-    u->rates = pa_alsa_get_supported_rates(u->pcm_handle);
+    u->rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
     if (!u->rates) {
         pa_log_error("Failed to find any supported sample rates.");
         goto fail;
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 802b51b..9f3170d 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1922,7 +1922,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
             pa_log_info("Disabling latency range changes on overrun");
     }
 
-    u->rates = pa_alsa_get_supported_rates(u->pcm_handle);
+    u->rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
     if (!u->rates) {
         pa_log_error("Failed to find any supported sample rates.");
         goto fail;
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 4a29a9a..114ab27 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1326,7 +1326,7 @@ char *pa_alsa_get_reserve_name(const char *device) {
     return pa_sprintf_malloc("Audio%i", i);
 }
 
-unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm) {
+unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
     static unsigned int all_rates[] = { 8000, 11025, 12000,
                                         16000, 22050, 24000,
                                         32000, 44100, 48000,
@@ -1352,17 +1352,27 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm) {
         }
     }
 
-    if (n == 0)
-        return NULL;
+    if (n > 0) {
+        rates = pa_xnew(unsigned int, n + 1);
 
-    rates = pa_xnew(unsigned int, n + 1);
+        for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
+            if (supported[i])
+                rates[j++] = all_rates[i];
+        }
 
-    for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
-        if (supported[i])
-            rates[j++] = all_rates[i];
-    }
+        rates[j] = 0;
+    } else {
+        rates = pa_xnew(unsigned int, 2);
 
-    rates[j] = 0;
+        rates[0] = fallback_rate;
+        if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
+            pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
+            pa_xfree(rates);
+            return NULL;
+        }
+
+        rates[1] = 0;
+    }
 
     return rates;
 }
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 236a329..1326e64 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -133,7 +133,7 @@ char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm);
 
 char *pa_alsa_get_reserve_name(const char *device);
 
-unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm);
+unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate);
 
 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm);
 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm);
-- 
1.8.0

_______________________________________________
pulseaudio-discuss mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

Reply via email to