--- sys/sys/soundcard.h 2024-09-23 07:37:50.791528000 +0800 +++ sys/sys/soundcard.h 2024-11-29 15:33:15.817113000 +0800 @@ -184,6 +184,7 @@ #define AFMT_S24_BE 0x00020000 /* Big endian signed 24-bit */ #define AFMT_U24_LE 0x00040000 /* Little endian unsigned 24-bit */ #define AFMT_U24_BE 0x00080000 /* Big endian unsigned 24-bit */ +#define AFMT_FLOAT 0x10000000 /* 32-bit floating point */ /* Machine dependent AFMT_* definitions. */ #if BYTE_ORDER == LITTLE_ENDIAN --- sys/dev/sound/pcm/channel.c 2024-11-27 07:37:35.185838000 +0800 +++ sys/dev/sound/pcm/channel.c 2024-11-29 15:33:15.817529000 +0800 @@ -980,6 +980,7 @@ { "u32le", NULL, NULL, AFMT_U32_LE }, { "u32be", NULL, NULL, AFMT_U32_BE }, { "ac3", NULL, NULL, AFMT_AC3 }, + { "float", NULL, NULL, AFMT_FLOAT }, { NULL, NULL, NULL, 0 } }; --- sys/dev/sound/pcm/feeder_format.c 2024-11-29 08:19:33.277658000 +0800 +++ sys/dev/sound/pcm/feeder_format.c 2024-11-29 15:35:04.228247000 +0800 @@ -35,6 +35,11 @@ #ifdef HAVE_KERNEL_OPTION_HEADERS #include "opt_snd.h" #endif +/* XXX for future opposite/odd endianess support */ +#undef SND_IEEE754_OE +#ifdef SND_IEEE754_OE +#include +#endif #include #include #include "feeder_if.h" @@ -172,6 +177,92 @@ PCM_WRITE_S16_NE(dst, 0); } +static __inline intpcm_t +intpcm_read_ieee754_32ne(uint8_t *src) +{ + uint32_t v; + int32_t s, e, m; + + v = *((uint32_t *)src); + + e = (v >> 23) & 0xff; + + /* NaN, +/- Inf or too small */ + if (e == 0xff || e < 96) + return (INTPCM_T(0)); + + s = ((v & 0x80000000U) != 0) ? 1 : 0; + + if (e > 126) + return (INTPCM_T((s == 0) ? PCM_S32_MAX : PCM_S32_MIN)); + + m = 0x800000 | (v & 0x7fffff); + e += 8 - 127; + + if (e < 0) + m >>= -e; + else + m <<= e; + + return (INTPCM_T((s == 0) ? m : -m)); +} + +static __inline void +intpcm_write_ieee754_32ne(uint8_t *dst, intpcm_t v) +{ + uint32_t r; + int32_t e; + + if (v == 0) + r = 0; + else if (v == PCM_S32_MAX) + r = 0x3f800000; + else if (v == PCM_S32_MIN) + r = 0x80000000U | 0x3f800000; + else { + r = 0; + if (v < 0) { + r |= 0x80000000U; + v = -v; + } + + e = 127 - 8; + while ((v & 0x7f000000) != 0) { + v >>= 1; + e++; + } + while ((v & 0x7f800000) == 0) { + v <<= 1; + e--; + } + + r |= (e & 0xff) << 23; + r |= v & 0x7fffff; + } + + *((uint32_t *)dst) = r; +} + +#ifdef SND_IEEE754_OE +static __inline intpcm_t +intpcm_read_ieee754_32oe(uint8_t *src) +{ + uint32_t v; + + v = bswap32(*((uint32_t *)src)); + + return (intpcm_read_ieee754_32ne((uint8_t *)&v)); +} + +static __inline void +intpcm_write_ieee754_32oe(uint8_t *dst, intpcm_t v) +{ + + intpcm_write_ieee754_32ne(dst, v); + *((uint32_t *)dst) = bswap32(*((uint32_t *)dst)); +} +#endif + #define FEEDFORMAT_ENTRY(SIGN, BIT, ENDIAN) \ { \ AFMT_##SIGN##BIT##_##ENDIAN, \ @@ -198,6 +289,10 @@ FEEDFORMAT_ENTRY(U, 16, BE), FEEDFORMAT_ENTRY(U, 24, BE), FEEDFORMAT_ENTRY(U, 32, BE), + { + AFMT_FLOAT, + intpcm_read_ieee754_32ne, intpcm_write_ieee754_32ne + }, { AFMT_MU_LAW, intpcm_read_ulaw, intpcm_write_ulaw --- sys/dev/sound/pcm/sound.h 2024-11-27 07:37:35.187046000 +0800 +++ sys/dev/sound/pcm/sound.h 2024-11-29 15:33:15.817853000 +0800 @@ -148,21 +148,27 @@ (((var)<(low))? (low) : ((var)>(high))? (high) : (var)) /* make figuring out what a format is easier. got AFMT_STEREO already */ -#define AFMT_32BIT (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE) +#define AFMT_32BIT (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE | \ + AFMT_FLOAT) #define AFMT_24BIT (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE) #define AFMT_16BIT (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE) #define AFMT_G711 (AFMT_MU_LAW | AFMT_A_LAW) #define AFMT_8BIT (AFMT_G711 | AFMT_U8 | AFMT_S8) #define AFMT_SIGNED (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE | AFMT_S24_BE | \ - AFMT_S16_LE | AFMT_S16_BE | AFMT_S8) -#define AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE | AFMT_U24_BE | \ + AFMT_S16_LE | AFMT_S16_BE | AFMT_S8 | AFMT_FLOAT) +#define _AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE | AFMT_U24_BE | \ AFMT_S16_BE | AFMT_U16_BE) +#if BYTE_ORDER == LITTLE_ENDIAN +#define AFMT_BIGENDIAN _AFMT_BIGENDIAN +#else /* !LITTLE_ENDIAN */ +#define AFMT_BIGENDIAN (_AFMT_BIGENDIAN | AFMT_FLOAT) +#endif /* LITTLE_ENDIAN */ #define AFMT_CONVERTIBLE (AFMT_8BIT | AFMT_16BIT | AFMT_24BIT | \ AFMT_32BIT) /* Supported vchan mixing formats */ -#define AFMT_VCHAN (AFMT_CONVERTIBLE & ~AFMT_G711) +#define AFMT_VCHAN (AFMT_CONVERTIBLE & ~(AFMT_G711 | AFMT_FLOAT)) #define AFMT_PASSTHROUGH AFMT_AC3 #define AFMT_PASSTHROUGH_RATE 48000