Browse Source

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 <hps@selasky.org>
pull/98/head
Hans Petter Selasky 5 years ago
parent
commit
88ec9ff24a
1 changed files with 93 additions and 95 deletions
  1. +93
    -95
      drivers/oss/oss_driver.c

+ 93
- 95
drivers/oss/oss_driver.c View File

@@ -23,6 +23,7 @@


#include <config.h> #include <config.h>


#define __BSD_VISIBLE 1
#ifdef USE_BARRIER #ifdef USE_BARRIER
/* /*
* POSIX conformance level should be globally defined somewhere, possibly * POSIX conformance level should be globally defined somewhere, possibly
@@ -57,6 +58,42 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/soundcard.h> #include <sys/soundcard.h>


#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 <jack/types.h> #include <jack/types.h>
#include <jack/thread.h> #include <jack/thread.h>


@@ -172,7 +209,9 @@ static void set_period_size (oss_driver_t *driver,
((double)driver->period_size / ((double)driver->period_size /
(double)driver->sample_rate) * 1e6; (double)driver->sample_rate) * 1e6;
driver->last_wait_ust = 0; 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->next_periodtime = 0;
driver->iodelay = 0.0F; 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) 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) { if (driver->next_periodtime > 0) {
driver->iodelay = (float) driver->iodelay = (float)
((long double)driver->last_periodtime - ((long double)driver->last_periodtime -
@@ -211,7 +252,7 @@ static void copy_and_convert_in (jack_sample_t *dst, void *src,
int dstidx; int dstidx;
signed short *s16src = (signed short*)src; signed short *s16src = (signed short*)src;
signed int *s32src = (signed int*)src; signed int *s32src = (signed int*)src;
double *f64src = (double*)src;
unsigned char *s24src = (unsigned char *)src;
jack_sample_t scale; jack_sample_t scale;


srcidx = channel; srcidx = channel;
@@ -225,10 +266,13 @@ static void copy_and_convert_in (jack_sample_t *dst, void *src,
} }
break; break;
case 24: case 24:
scale = 1.0f / 0x7fffff;
scale = 1.0f / 0x7fffffff;
for (dstidx = 0; dstidx < nframes; dstidx++) { for (dstidx = 0; dstidx < nframes; dstidx++) {
dst[dstidx] = (jack_sample_t) 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; srcidx += chcount;
} }
break; break;
@@ -240,12 +284,6 @@ static void copy_and_convert_in (jack_sample_t *dst, void *src,
srcidx += chcount; srcidx += chcount;
} }
break; 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 srcidx;
int dstidx; int dstidx;
signed short *s16dst = (signed short*)dst; signed short *s16dst = (signed short*)dst;
unsigned char *s24dst = (unsigned char *)dst;
signed int *s32dst = (signed int*)dst; signed int *s32dst = (signed int*)dst;
double *f64dst = (double*)dst;
jack_sample_t scale; jack_sample_t scale;


dstidx = channel; dstidx = channel;
@@ -273,12 +311,15 @@ static void copy_and_convert_out (void *dst, jack_sample_t *src,
} }
break; break;
case 24: case 24:
scale = 0x7fffff;
scale = 0x7fffffff;
for (srcidx = 0; srcidx < nframes; srcidx++) { 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; dstidx += chcount;
} }
break; break;
@@ -292,12 +333,6 @@ static void copy_and_convert_out (void *dst, jack_sample_t *src,
dstidx += chcount; dstidx += chcount;
} }
break; 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) 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 format;
int channels; int channels;
int samplerate; int samplerate;
@@ -441,19 +480,7 @@ static int oss_driver_start (oss_driver_t *driver)
const char *indev = driver->indev; const char *indev = driver->indev;
const char *outdev = driver->outdev; 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; driver->trigger = 0;
if (strcmp (indev, outdev) != 0) { if (strcmp (indev, outdev) != 0) {
if (driver->capture_channels > 0) { if (driver->capture_channels > 0) {
@@ -464,7 +491,7 @@ static int oss_driver_start (oss_driver_t *driver)
indev, __FILE__, __LINE__, errno); indev, __FILE__, __LINE__, errno);
} }
#ifndef OSS_NO_COOKED_MODE #ifndef OSS_NO_COOKED_MODE
ioctl (infd, SNDCTL_DSP_COOKEDMODE, &flags);
ioctl (infd, SNDCTL_DSP_COOKEDMODE, &cookedmode);
#endif #endif
fragsize = driver->period_size * fragsize = driver->period_size *
driver->capture_channels * samplesize; driver->capture_channels * samplesize;
@@ -479,7 +506,7 @@ static int oss_driver_start (oss_driver_t *driver)
outdev, __FILE__, __LINE__, errno); outdev, __FILE__, __LINE__, errno);
} }
#ifndef OSS_NO_COOKED_MODE #ifndef OSS_NO_COOKED_MODE
ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &flags);
ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &cookedmode);
#endif #endif
fragsize = driver->period_size * fragsize = driver->period_size *
driver->playback_channels * samplesize; driver->playback_channels * samplesize;
@@ -497,7 +524,7 @@ static int oss_driver_start (oss_driver_t *driver)
return -1; return -1;
} }
#ifndef OSS_NO_COOKED_MODE #ifndef OSS_NO_COOKED_MODE
ioctl (infd, SNDCTL_DSP_COOKEDMODE, &flags);
ioctl (infd, SNDCTL_DSP_COOKEDMODE, &cookedmode);
#endif #endif
} else if (driver->capture_channels == 0 && } else if (driver->capture_channels == 0 &&
driver->playback_channels != 0) { driver->playback_channels != 0) {
@@ -510,7 +537,7 @@ static int oss_driver_start (oss_driver_t *driver)
return -1; return -1;
} }
#ifndef OSS_NO_COOKED_MODE #ifndef OSS_NO_COOKED_MODE
ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &flags);
ioctl (outfd, SNDCTL_DSP_COOKEDMODE, &cookedmode);
#endif #endif
} else { } else {
infd = outfd = open (indev, O_RDWR | O_EXCL); infd = outfd = open (indev, O_RDWR | O_EXCL);
@@ -521,7 +548,7 @@ static int oss_driver_start (oss_driver_t *driver)
return -1; return -1;
} }
#ifndef OSS_NO_COOKED_MODE #ifndef OSS_NO_COOKED_MODE
ioctl (infd, SNDCTL_DSP_COOKEDMODE, &flags);
ioctl (infd, SNDCTL_DSP_COOKEDMODE, &cookedmode);
#endif #endif
} }
if (infd >= 0 && outfd >= 0) { if (infd >= 0 && outfd >= 0) {
@@ -705,7 +732,9 @@ static int oss_driver_start (oss_driver_t *driver)
sem_post (&driver->sem_start); 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->next_periodtime = 0;
driver->iodelay = 0.0F; driver->iodelay = 0.0F;


@@ -1143,6 +1172,27 @@ jack_driver_t * driver_initialize (jack_client_t *client,
pnode = jack_slist_next (pnode); 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->sample_rate = sample_rate;
driver->period_size = period_size; driver->period_size = period_size;
driver->nperiods = nperiods; driver->nperiods = nperiods;
@@ -1163,58 +1213,6 @@ jack_driver_t * driver_initialize (jack_client_t *client,
} }
driver->infd = -1; driver->infd = -1;
driver->outfd = -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->indevbuf = driver->outdevbuf = NULL;


driver->capture_ports = NULL; driver->capture_ports = NULL;


Loading…
Cancel
Save