summaryrefslogtreecommitdiffstats
path: root/sys/oss
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2004-03-23 04:01:27 +0000
committerDavid Schleef <ds@schleef.org>2004-03-23 04:01:27 +0000
commit3cd8eca7f3ae6762de6218dda747ef63aa988115 (patch)
tree68d906d69145794a50364f6339a100477ca17448 /sys/oss
parent17e66fd9064d502a33fc989d49d53bfa2e7ae560 (diff)
sys/oss/: Rate probing test app.
Original commit message from CVS: * sys/oss/Makefile.am: * sys/oss/oss_probe.c: (main), (probe_check), (add_range), (check_rate), (add_rate): Rate probing test app.
Diffstat (limited to 'sys/oss')
-rw-r--r--sys/oss/Makefile.am7
-rw-r--r--sys/oss/oss_probe.c234
2 files changed, 241 insertions, 0 deletions
diff --git a/sys/oss/Makefile.am b/sys/oss/Makefile.am
index e8995bc5..5480bb7e 100644
--- a/sys/oss/Makefile.am
+++ b/sys/oss/Makefile.am
@@ -14,3 +14,10 @@ noinst_HEADERS = gstosssink.h \
gstosssrc.h \
gstosselement.h\
gstossmixer.h
+
+noinst_PROGRAMS = oss_probe
+
+oss_probe_SOURCES = oss_probe.c
+oss_probe_CFLAGS = $(GLIB_CFLAGS)
+oss_probe_LDADD = $(GLIB_LIBS)
+
diff --git a/sys/oss/oss_probe.c b/sys/oss/oss_probe.c
new file mode 100644
index 00000000..dca158a9
--- /dev/null
+++ b/sys/oss/oss_probe.c
@@ -0,0 +1,234 @@
+
+#include <sys/soundcard.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <glib.h>
+
+typedef struct _Probe Probe;
+struct _Probe
+{
+ int fd;
+ int format;
+ int n_channels;
+ GArray *rates;
+};
+
+typedef struct _Range Range;
+struct _Range
+{
+ int min;
+ int max;
+};
+
+static gboolean probe_check (Probe * probe);
+static int check_rate (Probe * probe, int irate);
+static GList *add_range (GList * list, int min, int max);
+static void add_rate (GArray * array, int rate);
+
+int
+main (int argc, char *argv[])
+{
+ int fd;
+ int n;
+ int *rates;
+ int i;
+ Probe *probe;
+
+ fd = open ("/dev/dsp", O_RDWR);
+ if (fd < 0) {
+ perror ("/dev/dsp");
+ exit (1);
+ }
+
+ probe = g_new0 (Probe, 1);
+ probe->fd = fd;
+ probe->format = AFMT_S16_LE;
+ probe->n_channels = 2;
+
+ probe_check (probe);
+ for (i = 0; i < probe->rates->len; i++) {
+ g_print ("%d\n", g_array_index (probe->rates, int, i));
+ }
+
+#if 0
+ probe = g_new0 (Probe, 1);
+ probe->fd = fd;
+ probe->format = AFMT_S16_LE;
+ probe->n_channels = 1;
+
+ probe_check (probe);
+ for (i = 0; i < probe->rates->len; i++) {
+ g_print ("%d\n", g_array_index (probe->rates, int, i));
+ }
+
+ probe = g_new0 (Probe, 1);
+ probe->fd = fd;
+ probe->format = AFMT_U8;
+ probe->n_channels = 2;
+
+ probe_check (probe);
+ for (i = 0; i < probe->rates->len; i++) {
+ g_print ("%d\n", g_array_index (probe->rates, int, i));
+ }
+
+ probe = g_new0 (Probe, 1);
+ probe->fd = fd;
+ probe->format = AFMT_U8;
+ probe->n_channels = 1;
+
+ probe_check (probe);
+ for (i = 0; i < probe->rates->len; i++) {
+ g_print ("%d\n", g_array_index (probe->rates, int, i));
+ }
+#endif
+
+ return 0;
+}
+
+static gboolean
+probe_check (Probe * probe)
+{
+ GList *item;
+ Range *range;
+ GList *new_ranges;
+ GList *ranges;
+ int i;
+ int min, max;
+ int exact_rates = 0;
+ gboolean checking_exact_rates = TRUE;
+ int n_checks = 0;
+
+ probe->rates = g_array_new (FALSE, FALSE, sizeof (int));
+
+ min = check_rate (probe, 1000);
+ add_rate (probe->rates, min);
+ n_checks++;
+ max = check_rate (probe, 100000);
+ add_rate (probe->rates, max);
+ n_checks++;
+ ranges = add_range (NULL, min + 1, max - 1);
+
+ for (i = 0; i < 20; i++) {
+ new_ranges = NULL;
+
+ if (ranges == NULL) {
+ g_print ("no more ranges, probe complete\n");
+ g_print ("n_checks = %d\n", n_checks);
+
+ return TRUE;
+ }
+ for (item = ranges; item; item = item->next) {
+ int min1;
+ int max1;
+ int mid;
+ int mid_ret;
+
+ range = item->data;
+
+ g_print ("checking [%d,%d]\n", range->min, range->max);
+
+ mid = (range->min + range->max) / 2;
+ mid_ret = check_rate (probe, mid);
+ n_checks++;
+
+ if (mid == mid_ret && checking_exact_rates) {
+ exact_rates++;
+ if (exact_rates > 100) {
+ g_print ("got 100 exact rates, assuming all are exact\n");
+ return 0;
+ }
+ } else {
+ checking_exact_rates = FALSE;
+ }
+
+ add_rate (probe->rates, mid_ret);
+
+#if 1
+ /* Assume that the rate is arithmetically rounded to the nearest
+ * supported rate. */
+ if (mid < mid_ret) {
+ min1 = mid - (mid_ret - mid);
+ max1 = mid_ret + 1;
+ } else {
+ min1 = mid_ret - 1;
+ max1 = mid + (mid - mid_ret);
+ }
+#else
+ /* Assume that the rate is not rounded past a supported rate */
+ if (mid < mid_ret) {
+ min1 = mid - 1;
+ max1 = mid_ret + 1;
+ } else {
+ min1 = mid_ret - 1;
+ max1 = mid + 1;
+ }
+#endif
+
+ if (range->min < min1) {
+ new_ranges = add_range (new_ranges, range->min, min1);
+ }
+ if (max1 < range->max) {
+ new_ranges = add_range (new_ranges, max1, range->max);
+ }
+ }
+
+ /* leak ranges */
+
+ ranges = new_ranges;
+ }
+
+ return 0;
+}
+
+static GList *
+add_range (GList * list, int min, int max)
+{
+ Range *range = g_new0 (Range, 1);
+
+ range->min = min;
+ range->max = max;
+
+ return g_list_append (list, range);
+}
+
+static int
+check_rate (Probe * probe, int irate)
+{
+ int rate;
+ int format;
+ int n_channels;
+
+ rate = irate;
+ format = probe->format;
+ n_channels = probe->n_channels;
+
+ ioctl (probe->fd, SNDCTL_DSP_SETFMT, &format);
+ ioctl (probe->fd, SNDCTL_DSP_CHANNELS, &n_channels);
+ ioctl (probe->fd, SNDCTL_DSP_SPEED, &rate);
+
+ g_print ("rate %d -> %d\n", irate, rate);
+
+ if (rate == irate - 1 || rate == irate + 1) {
+ rate = irate;
+ }
+ return rate;
+}
+
+static void
+add_rate (GArray * array, int rate)
+{
+ int i;
+ int val;
+
+ for (i = 0; i < array->len; i++) {
+ val = g_array_index (array, int, i);
+
+ if (val == rate)
+ return;
+ }
+ g_print ("supported rate: %d\n", rate);
+ g_array_append_val (array, rate);
+}