From 88ec9ff24aed61a720eb0c6148a3f79ee98d0754 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 26 Aug 2020 14:10:28 +0200 Subject: [PATCH] Improve OSS backend support for JACK on non-Linux systems. While at it remove double, 64-bit sample support, because it is not even supported by Linux's OSS kernel driver. A subtle difference is that BSD systems use packed 24-bit sample mode by default. While Linux doesn't. Signed-off-by: Hans Petter Selasky --- drivers/oss/oss_driver.c | 188 +++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 95 deletions(-) diff --git a/drivers/oss/oss_driver.c b/drivers/oss/oss_driver.c index f53a2dd4..6968ed76 100644 --- a/drivers/oss/oss_driver.c +++ b/drivers/oss/oss_driver.c @@ -23,6 +23,7 @@ #include +#define __BSD_VISIBLE 1 #ifdef USE_BARRIER /* * POSIX conformance level should be globally defined somewhere, possibly @@ -57,6 +58,42 @@ #include #include +#ifdef __linux__ +#define AFMT_S32_LE 0x00001000 +#define AFMT_S32_BE 0x00002000 +#define AFMT_S24_LE 0x00008000 +#define AFMT_S24_BE 0x00010000 +#define AFMT_S24_PACKED 0x00040000 + +#ifndef OSS_ENDIAN +#ifdef __GNUC__ +#if (defined(__i386__) || defined(__alpha__) || defined(__arm__) || defined(__x86_64__) || (defined(__sh__) && !defined(__LITTLE_ENDIAN__))) +#define OSS_LITTLE_ENDIAN 1234 +#define OSS_ENDIAN OSS_LITTLE_ENDIAN +#else +#define OSS_BIG_ENDIAN 4321 +#define OSS_ENDIAN OSS_BIG_ENDIAN +#endif +#else /* __GNUC__ */ +#if (defined(_AIX) || defined(AIX) || defined(sparc) || defined(__hppa) || defined(PPC) || defined(__powerpc__) && !defined(i386) && !defined(__i386) && !defined(__i386__)) +#define OSS_BIG_ENDIAN 4321 +#define OSS_ENDIAN OSS_BIG_ENDIAN +#else +#define OSS_LITTLE_ENDIAN 1234 +#define OSS_ENDIAN OSS_LITTLE_ENDIAN +#endif +#endif /* __GNUC__ */ +#endif /* OSS_ENDIAN */ + +#if (OSS_ENDIAN == 1234) +#define AFMT_S16_NE AFMT_S16_LE +#define AFMT_S32_NE AFMT_S32_LE +#else +#define AFMT_S16_NE AFMT_S16_BE +#define AFMT_S32_NE AFMT_S32_BE +#endif +#endif + #include #include @@ -172,7 +209,9 @@ static void set_period_size (oss_driver_t *driver, ((double)driver->period_size / (double)driver->sample_rate) * 1e6; driver->last_wait_ust = 0; - driver->last_periodtime = driver->engine->get_microseconds (); + driver->last_periodtime = driver->engine ? + driver->engine->get_microseconds() : + jack_get_microseconds(); driver->next_periodtime = 0; driver->iodelay = 0.0F; } @@ -180,7 +219,9 @@ static void set_period_size (oss_driver_t *driver, static inline void update_times (oss_driver_t *driver) { - driver->last_periodtime = driver->engine->get_microseconds (); + driver->last_periodtime = driver->engine ? + driver->engine->get_microseconds() : + jack_get_microseconds(); if (driver->next_periodtime > 0) { driver->iodelay = (float) ((long double)driver->last_periodtime - @@ -211,7 +252,7 @@ static void copy_and_convert_in (jack_sample_t *dst, void *src, int dstidx; signed short *s16src = (signed short*)src; signed int *s32src = (signed int*)src; - double *f64src = (double*)src; + unsigned char *s24src = (unsigned char *)src; jack_sample_t scale; srcidx = channel; @@ -225,10 +266,13 @@ static void copy_and_convert_in (jack_sample_t *dst, void *src, } break; case 24: - scale = 1.0f / 0x7fffff; + scale = 1.0f / 0x7fffffff; for (dstidx = 0; dstidx < nframes; dstidx++) { dst[dstidx] = (jack_sample_t) - s32src[srcidx] * scale; + ((signed int)( + (s24src[3 * srcidx + 2] << 24) | + (s24src[3 * srcidx + 1] << 16) | + (s24src[3 * srcidx + 0] << 8))) * scale; srcidx += chcount; } break; @@ -240,12 +284,6 @@ static void copy_and_convert_in (jack_sample_t *dst, void *src, srcidx += chcount; } break; - case 64: - for (dstidx = 0; dstidx < nframes; dstidx++) { - dst[dstidx] = (jack_sample_t)f64src[srcidx]; - srcidx += chcount; - } - break; } } @@ -256,8 +294,8 @@ static void copy_and_convert_out (void *dst, jack_sample_t *src, int srcidx; int dstidx; signed short *s16dst = (signed short*)dst; + unsigned char *s24dst = (unsigned char *)dst; signed int *s32dst = (signed int*)dst; - double *f64dst = (double*)dst; jack_sample_t scale; dstidx = channel; @@ -273,12 +311,15 @@ static void copy_and_convert_out (void *dst, jack_sample_t *src, } break; case 24: - scale = 0x7fffff; + scale = 0x7fffffff; for (srcidx = 0; srcidx < nframes; srcidx++) { - s32dst[dstidx] = (signed int) - (src[srcidx] >= 0.0f) ? - (src[srcidx] * scale + 0.5f) : - (src[srcidx] * scale - 0.5f); + signed int sample = + (src[srcidx] >= 0.0f) ? + (src[srcidx] * scale + 0.5f) : + (src[srcidx] * scale - 0.5f) ; + s24dst[3*dstidx + 2] = sample >> 24; + s24dst[3*dstidx + 1] = sample >> 16; + s24dst[3*dstidx + 0] = sample >> 8; dstidx += chcount; } break; @@ -292,12 +333,6 @@ static void copy_and_convert_out (void *dst, jack_sample_t *src, dstidx += chcount; } break; - case 64: - for (srcidx = 0; srcidx < nframes; srcidx++) { - f64dst[dstidx] = (double)src[srcidx]; - dstidx += chcount; - } - break; } } @@ -429,7 +464,11 @@ static int oss_driver_detach (oss_driver_t *driver, jack_engine_t *engine) static int oss_driver_start (oss_driver_t *driver) { - int flags = 0; +#if defined(OPTION_COOKEDMODE) + int cookedmode = 1; +#else + int cookedmode = 0; +#endif int format; int channels; int samplerate; @@ -441,19 +480,7 @@ static int oss_driver_start (oss_driver_t *driver) const char *indev = driver->indev; const char *outdev = driver->outdev; - switch (driver->bits) { - case 24: - case 32: - samplesize = sizeof(int); - break; - case 64: - samplesize = sizeof(double); - break; - case 16: - default: - samplesize = sizeof(short); - break; - } + samplesize = driver->bits / 8; driver->trigger = 0; if (strcmp (indev, outdev) != 0) { if (driver->capture_channels > 0) { @@ -464,7 +491,7 @@ static int oss_driver_start (oss_driver_t *driver) indev, __FILE__, __LINE__, errno); } #ifndef OSS_NO_COOKED_MODE - ioctl (infd, SNDCTL_DSP_COOKEDMODE, &flags); + ioctl (infd, SNDCTL_DSP_COOKEDMODE, &cookedmode); #endif fragsize = driver->period_size * driver->capture_channels * samplesize; @@ -479,7 +506,7 @@ static int oss_driver_start (oss_driver_t *driver) outdev, __FILE__, __LINE__, errno); } #ifndef OSS_NO_COOKED_MODE - ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &flags); + ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &cookedmode); #endif fragsize = driver->period_size * driver->playback_channels * samplesize; @@ -497,7 +524,7 @@ static int oss_driver_start (oss_driver_t *driver) return -1; } #ifndef OSS_NO_COOKED_MODE - ioctl (infd, SNDCTL_DSP_COOKEDMODE, &flags); + ioctl (infd, SNDCTL_DSP_COOKEDMODE, &cookedmode); #endif } else if (driver->capture_channels == 0 && driver->playback_channels != 0) { @@ -510,7 +537,7 @@ static int oss_driver_start (oss_driver_t *driver) return -1; } #ifndef OSS_NO_COOKED_MODE - ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &flags); + ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &cookedmode); #endif } else { infd = outfd = open (indev, O_RDWR | O_EXCL); @@ -521,7 +548,7 @@ static int oss_driver_start (oss_driver_t *driver) return -1; } #ifndef OSS_NO_COOKED_MODE - ioctl (infd, SNDCTL_DSP_COOKEDMODE, &flags); + ioctl (infd, SNDCTL_DSP_COOKEDMODE, &cookedmode); #endif } if (infd >= 0 && outfd >= 0) { @@ -705,7 +732,9 @@ static int oss_driver_start (oss_driver_t *driver) sem_post (&driver->sem_start); } - driver->last_periodtime = driver->engine->get_microseconds (); + driver->last_periodtime = driver->engine ? + driver->engine->get_microseconds() : + jack_get_microseconds(); driver->next_periodtime = 0; driver->iodelay = 0.0F; @@ -1143,6 +1172,27 @@ jack_driver_t * driver_initialize (jack_client_t *client, pnode = jack_slist_next (pnode); } + switch (bits) + { + case 16: /* native-endian 16-bit integer */ + driver->format = AFMT_S16_NE; + break; + case 24: /* little-endian 24-bit integer */ +#ifdef __linux__ + driver->format = AFMT_S24_PACKED; +#else + driver->format = AFMT_S24_LE; +#endif + break; + case 32: /* native-endian 32-bit integer */ + driver->format = AFMT_S32_NE; + break; + default: + free(driver); + jack_error("OSS: invalid number of bits: %d", + __FILE__, __LINE__, bits); + return NULL; + } driver->sample_rate = sample_rate; driver->period_size = period_size; driver->nperiods = nperiods; @@ -1163,58 +1213,6 @@ jack_driver_t * driver_initialize (jack_client_t *client, } driver->infd = -1; driver->outfd = -1; - switch (driver->bits) { -# ifndef OSS_ENDIAN -# ifdef __GNUC__ -# if (defined(__i386__) || defined(__alpha__) || defined(__arm__) || defined(__x86_64__) || (defined(__sh__) && !defined(__LITTLE_ENDIAN__))) -# define OSS_LITTLE_ENDIAN 1234 -# define OSS_ENDIAN OSS_LITTLE_ENDIAN -# else -# define OSS_BIG_ENDIAN 4321 -# define OSS_ENDIAN OSS_BIG_ENDIAN -# endif -# else /* __GNUC__ */ -# if (defined(_AIX) || defined(AIX) || defined(sparc) || defined(__hppa) || defined(PPC) || defined(__powerpc__) && !defined(i386) && !defined(__i386) && !defined(__i386__)) -# define OSS_BIG_ENDIAN 4321 -# define OSS_ENDIAN OSS_BIG_ENDIAN -# else -# define OSS_LITTLE_ENDIAN 1234 -# define OSS_ENDIAN OSS_LITTLE_ENDIAN -# endif -# endif /* __GNUC__ */ -# endif /* OSS_ENDIAN */ -# if (OSS_ENDIAN == 1234) - /* little-endian architectures */ - case 24: /* little-endian LSB aligned 24-bits in 32-bits integer */ - driver->format = 0x00008000; - break; - case 32: /* little-endian 32-bit integer */ - driver->format = 0x00001000; - break; - case 64: /* native-endian 64-bit float */ - driver->format = 0x00004000; - break; - case 16: /* little-endian 16-bit integer */ - default: - driver->format = 0x00000010; - break; - /* big-endian architectures */ -# else - case 24: /* big-endian LSB aligned 24-bits in 32-bits integer */ - break; - driver->format = 0x00010000; - case 32: /* big-endian 32-bit integer */ - driver->format = 0x00002000; - break; - case 64: /* native-endian 64-bit float */ - driver->format = 0x00004000; - break; - case 16: /* big-endian 16-bit integer */ - default: - driver->format = 0x00000020; -# endif - } - driver->indevbuf = driver->outdevbuf = NULL; driver->capture_ports = NULL;