Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109550211
D48330.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D48330.diff
View Options
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -147,70 +147,6 @@
#define RANGE(var, low, high) (var) = \
(((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_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_BE | AFMT_U16_BE)
-
-#define AFMT_CONVERTIBLE (AFMT_8BIT | AFMT_16BIT | AFMT_24BIT | \
- AFMT_32BIT)
-
-/* Supported vchan mixing formats */
-#define AFMT_VCHAN (AFMT_CONVERTIBLE & ~AFMT_G711)
-
-#define AFMT_PASSTHROUGH AFMT_AC3
-#define AFMT_PASSTHROUGH_RATE 48000
-#define AFMT_PASSTHROUGH_CHANNEL 2
-#define AFMT_PASSTHROUGH_EXTCHANNEL 0
-
-/*
- * We're simply using unused, contiguous bits from various AFMT_ definitions.
- * ~(0xb00ff7ff)
- */
-#define AFMT_ENCODING_MASK 0xf00fffff
-#define AFMT_CHANNEL_MASK 0x07f00000
-#define AFMT_CHANNEL_SHIFT 20
-#define AFMT_CHANNEL_MAX 0x7f
-#define AFMT_EXTCHANNEL_MASK 0x08000000
-#define AFMT_EXTCHANNEL_SHIFT 27
-#define AFMT_EXTCHANNEL_MAX 1
-
-#define AFMT_ENCODING(v) ((v) & AFMT_ENCODING_MASK)
-
-#define AFMT_EXTCHANNEL(v) (((v) & AFMT_EXTCHANNEL_MASK) >> \
- AFMT_EXTCHANNEL_SHIFT)
-
-#define AFMT_CHANNEL(v) (((v) & AFMT_CHANNEL_MASK) >> \
- AFMT_CHANNEL_SHIFT)
-
-#define AFMT_BIT(v) (((v) & AFMT_32BIT) ? 32 : \
- (((v) & AFMT_24BIT) ? 24 : \
- ((((v) & AFMT_16BIT) || \
- ((v) & AFMT_PASSTHROUGH)) ? 16 : 8)))
-
-#define AFMT_BPS(v) (AFMT_BIT(v) >> 3)
-#define AFMT_ALIGN(v) (AFMT_BPS(v) * AFMT_CHANNEL(v))
-
-#define SND_FORMAT(f, c, e) (AFMT_ENCODING(f) | \
- (((c) << AFMT_CHANNEL_SHIFT) & \
- AFMT_CHANNEL_MASK) | \
- (((e) << AFMT_EXTCHANNEL_SHIFT) & \
- AFMT_EXTCHANNEL_MASK))
-
-#define AFMT_U8_NE AFMT_U8
-#define AFMT_S8_NE AFMT_S8
-
-#define AFMT_SIGNED_NE (AFMT_S8_NE | AFMT_S16_NE | AFMT_S24_NE | AFMT_S32_NE)
-
-#define AFMT_NE (AFMT_SIGNED_NE | AFMT_U8_NE | AFMT_U16_NE | \
- AFMT_U24_NE | AFMT_U32_NE)
-
enum {
SND_DEV_CTL = 0, /* Control port /dev/mixer */
SND_DEV_SEQ, /* Sequencer /dev/sequencer */
@@ -508,4 +444,68 @@
#endif /* _KERNEL */
+/* 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_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_BE | AFMT_U16_BE)
+
+#define AFMT_CONVERTIBLE (AFMT_8BIT | AFMT_16BIT | AFMT_24BIT | \
+ AFMT_32BIT)
+
+/* Supported vchan mixing formats */
+#define AFMT_VCHAN (AFMT_CONVERTIBLE & ~AFMT_G711)
+
+#define AFMT_PASSTHROUGH AFMT_AC3
+#define AFMT_PASSTHROUGH_RATE 48000
+#define AFMT_PASSTHROUGH_CHANNEL 2
+#define AFMT_PASSTHROUGH_EXTCHANNEL 0
+
+/*
+ * We're simply using unused, contiguous bits from various AFMT_ definitions.
+ * ~(0xb00ff7ff)
+ */
+#define AFMT_ENCODING_MASK 0xf00fffff
+#define AFMT_CHANNEL_MASK 0x07f00000
+#define AFMT_CHANNEL_SHIFT 20
+#define AFMT_CHANNEL_MAX 0x7f
+#define AFMT_EXTCHANNEL_MASK 0x08000000
+#define AFMT_EXTCHANNEL_SHIFT 27
+#define AFMT_EXTCHANNEL_MAX 1
+
+#define AFMT_ENCODING(v) ((v) & AFMT_ENCODING_MASK)
+
+#define AFMT_EXTCHANNEL(v) (((v) & AFMT_EXTCHANNEL_MASK) >> \
+ AFMT_EXTCHANNEL_SHIFT)
+
+#define AFMT_CHANNEL(v) (((v) & AFMT_CHANNEL_MASK) >> \
+ AFMT_CHANNEL_SHIFT)
+
+#define AFMT_BIT(v) (((v) & AFMT_32BIT) ? 32 : \
+ (((v) & AFMT_24BIT) ? 24 : \
+ ((((v) & AFMT_16BIT) || \
+ ((v) & AFMT_PASSTHROUGH)) ? 16 : 8)))
+
+#define AFMT_BPS(v) (AFMT_BIT(v) >> 3)
+#define AFMT_ALIGN(v) (AFMT_BPS(v) * AFMT_CHANNEL(v))
+
+#define SND_FORMAT(f, c, e) (AFMT_ENCODING(f) | \
+ (((c) << AFMT_CHANNEL_SHIFT) & \
+ AFMT_CHANNEL_MASK) | \
+ (((e) << AFMT_EXTCHANNEL_SHIFT) & \
+ AFMT_EXTCHANNEL_MASK))
+
+#define AFMT_U8_NE AFMT_U8
+#define AFMT_S8_NE AFMT_S8
+
+#define AFMT_SIGNED_NE (AFMT_S8_NE | AFMT_S16_NE | AFMT_S24_NE | AFMT_S32_NE)
+
+#define AFMT_NE (AFMT_SIGNED_NE | AFMT_U8_NE | AFMT_U16_NE | \
+ AFMT_U24_NE | AFMT_U32_NE)
+
#endif /* _OS_H_ */
diff --git a/tests/sys/sound/Makefile b/tests/sys/sound/Makefile
--- a/tests/sys/sound/Makefile
+++ b/tests/sys/sound/Makefile
@@ -2,8 +2,12 @@
TESTSDIR= ${TESTSBASE}/sys/sound
+ATF_TESTS_C+= pcm_read_write
ATF_TESTS_C+= sndstat
+CFLAGS+= -I${SRCTOP}/sys
LDFLAGS+= -lnv
+CFLAGS.pcm_read_write.c+= -Wno-cast-align
+
.include <bsd.test.mk>
diff --git a/tests/sys/sound/pcm_read_write.c b/tests/sys/sound/pcm_read_write.c
new file mode 100644
--- /dev/null
+++ b/tests/sys/sound/pcm_read_write.c
@@ -0,0 +1,509 @@
+/*-
+ * Copyright (c) 2025 Florian Walpen
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * These tests exercise conversion functions of the sound module, used to read
+ * pcm samples from a buffer, and write pcm samples to a buffer. The test cases
+ * are non-exhaustive, but should detect systematic errors in conversion of the
+ * various sample formats supported. In particular, the test cases establish
+ * correctness independent of the machine's endianness, making them suitable to
+ * check for architecture-specific problems.
+ */
+
+#include <sys/types.h>
+#include <sys/soundcard.h>
+
+#include <atf-c.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/pcm/pcm.h>
+#include <dev/sound/pcm/g711.h>
+
+/* Generic test data, with buffer content matching the sample values. */
+struct afmt_test_data {
+ const char *label;
+ uint8_t buffer[4];
+ size_t size;
+ int format;
+ intpcm_t value;
+ _Static_assert((sizeof(intpcm_t) == 4),
+ "Test data assumes 32bit, adjust negative values to new size.");
+} static const afmt_tests[] = {
+ /* 8 bit sample formats. */
+ {"s8_1", {0x01, 0x00, 0x00, 0x00}, 1, AFMT_S8, 0x00000001},
+ {"s8_2", {0x81, 0x00, 0x00, 0x00}, 1, AFMT_S8, 0xffffff81},
+ {"u8_1", {0x01, 0x00, 0x00, 0x00}, 1, AFMT_U8, 0xffffff81},
+ {"u8_2", {0x81, 0x00, 0x00, 0x00}, 1, AFMT_U8, 0x00000001},
+
+ /* 16 bit sample formats. */
+ {"s16le_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_S16_LE, 0x00000201},
+ {"s16le_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_S16_LE, 0xffff8281},
+ {"s16be_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_S16_BE, 0x00000102},
+ {"s16be_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_S16_BE, 0xffff8182},
+ {"u16le_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_U16_LE, 0xffff8201},
+ {"u16le_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_U16_LE, 0x00000281},
+ {"u16be_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_U16_BE, 0xffff8102},
+ {"u16be_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_U16_BE, 0x00000182},
+
+ /* 24 bit sample formats. */
+ {"s24le_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_S24_LE, 0x00030201},
+ {"s24le_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_S24_LE, 0xff838281},
+ {"s24be_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_S24_BE, 0x00010203},
+ {"s24be_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_S24_BE, 0xff818283},
+ {"u24le_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_U24_LE, 0xff830201},
+ {"u24le_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_U24_LE, 0x00038281},
+ {"u24be_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_U24_BE, 0xff810203},
+ {"u24be_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_U24_BE, 0x00018283},
+
+ /* 32 bit sample formats. */
+ {"s32le_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_S32_LE, 0x04030201},
+ {"s32le_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_S32_LE, 0x84838281},
+ {"s32be_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_S32_BE, 0x01020304},
+ {"s32be_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_S32_BE, 0x81828384},
+ {"u32le_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_U32_LE, 0x84030201},
+ {"u32le_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_U32_LE, 0x04838281},
+ {"u32be_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_U32_BE, 0x81020304},
+ {"u32be_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_U32_BE, 0x01828384},
+
+ /* u-law and A-law sample formats. */
+ {"mulaw_1", {0x01, 0x00, 0x00, 0x00}, 1, AFMT_MU_LAW, 0xffffff87},
+ {"mulaw_2", {0x81, 0x00, 0x00, 0x00}, 1, AFMT_MU_LAW, 0x00000079},
+ {"alaw_1", {0x2a, 0x00, 0x00, 0x00}, 1, AFMT_A_LAW, 0xffffff83},
+ {"alaw_2", {0xab, 0x00, 0x00, 0x00}, 1, AFMT_A_LAW, 0x00000079}
+};
+
+/* Normalize sample values in strictly correct (but slow) c. */
+static intpcm_t
+local_normalize(intpcm_t value, int val_bits, int norm_bits)
+{
+ /* Avoid undefined or implementation defined behavior. */
+ if (val_bits < norm_bits)
+ /* Multiply instead of left shift (value may be negative). */
+ return (value * (1 << (norm_bits - val_bits)));
+ else if (val_bits > norm_bits)
+ /* Divide instead of right shift (value may be negative). */
+ return (value / (1 << (val_bits - norm_bits)));
+ return value;
+}
+
+/* Restrict magnitude of sample value to 24bit for 32bit calculations. */
+static intpcm_t
+local_calc_limit(intpcm_t value, int val_bits)
+{
+ /* Avoid implementation defined behavior. */
+ if (sizeof(intpcm32_t) == 32 && val_bits == 32)
+ /* Divide instead of right shift (value may be negative). */
+ return (value / (1 << 8));
+ return value;
+}
+
+/* Lookup tables to read u-law and A-law sample formats. */
+static const uint8_t ulaw_to_u8[G711_TABLE_SIZE] = ULAW_TO_U8;
+static const uint8_t alaw_to_u8[G711_TABLE_SIZE] = ALAW_TO_U8;
+
+/* Helper function to read one sample value from a buffer. */
+static intpcm_t
+local_pcm_read(uint8_t *src, uint32_t format)
+{
+ intpcm_t value;
+
+ switch (format) {
+ case AFMT_S8:
+ value = _PCM_READ_S8_NE(src);
+ break;
+ case AFMT_U8:
+ value = _PCM_READ_U8_NE(src);
+ break;
+ case AFMT_S16_LE:
+ value = _PCM_READ_S16_LE(src);
+ break;
+ case AFMT_S16_BE:
+ value = _PCM_READ_S16_BE(src);
+ break;
+ case AFMT_U16_LE:
+ value = _PCM_READ_U16_LE(src);
+ break;
+ case AFMT_U16_BE:
+ value = _PCM_READ_U16_BE(src);
+ break;
+ case AFMT_S24_LE:
+ value = _PCM_READ_S24_LE(src);
+ break;
+ case AFMT_S24_BE:
+ value = _PCM_READ_S24_BE(src);
+ break;
+ case AFMT_U24_LE:
+ value = _PCM_READ_U24_LE(src);
+ break;
+ case AFMT_U24_BE:
+ value = _PCM_READ_U24_BE(src);
+ break;
+ case AFMT_S32_LE:
+ value = _PCM_READ_S32_LE(src);
+ break;
+ case AFMT_S32_BE:
+ value = _PCM_READ_S32_BE(src);
+ break;
+ case AFMT_U32_LE:
+ value = _PCM_READ_U32_LE(src);
+ break;
+ case AFMT_U32_BE:
+ value = _PCM_READ_U32_BE(src);
+ break;
+ case AFMT_MU_LAW:
+ value = _G711_TO_INTPCM(ulaw_to_u8, *src);
+ break;
+ case AFMT_A_LAW:
+ value = _G711_TO_INTPCM(alaw_to_u8, *src);
+ break;
+ default:
+ value = 0;
+ }
+
+ return (value);
+}
+
+/* Helper function to read one sample value from a buffer for calculations. */
+static intpcm_t
+local_pcm_read_calc(uint8_t *src, uint32_t format)
+{
+ intpcm_t value;
+
+ switch (format) {
+ case AFMT_S8:
+ value = PCM_READ_S8_NE(src);
+ break;
+ case AFMT_U8:
+ value = PCM_READ_U8_NE(src);
+ break;
+ case AFMT_S16_LE:
+ value = PCM_READ_S16_LE(src);
+ break;
+ case AFMT_S16_BE:
+ value = PCM_READ_S16_BE(src);
+ break;
+ case AFMT_U16_LE:
+ value = PCM_READ_U16_LE(src);
+ break;
+ case AFMT_U16_BE:
+ value = PCM_READ_U16_BE(src);
+ break;
+ case AFMT_S24_LE:
+ value = PCM_READ_S24_LE(src);
+ break;
+ case AFMT_S24_BE:
+ value = PCM_READ_S24_BE(src);
+ break;
+ case AFMT_U24_LE:
+ value = PCM_READ_U24_LE(src);
+ break;
+ case AFMT_U24_BE:
+ value = PCM_READ_U24_BE(src);
+ break;
+ case AFMT_S32_LE:
+ value = PCM_READ_S32_LE(src);
+ break;
+ case AFMT_S32_BE:
+ value = PCM_READ_S32_BE(src);
+ break;
+ case AFMT_U32_LE:
+ value = PCM_READ_U32_LE(src);
+ break;
+ case AFMT_U32_BE:
+ value = PCM_READ_U32_BE(src);
+ break;
+ case AFMT_MU_LAW:
+ value = _G711_TO_INTPCM(ulaw_to_u8, *src);
+ break;
+ case AFMT_A_LAW:
+ value = _G711_TO_INTPCM(alaw_to_u8, *src);
+ break;
+ default:
+ value = 0;
+ }
+
+ return (value);
+}
+
+/* Helper function to read one normalized sample from a buffer. */
+static intpcm_t
+local_pcm_read_norm(uint8_t *src, uint32_t format)
+{
+ intpcm_t value;
+
+ value = local_pcm_read(src, format);
+ value <<= (32 - AFMT_BIT(format));
+ return (value);
+}
+
+/* Lookup tables to write u-law and A-law sample formats. */
+static const uint8_t u8_to_ulaw[G711_TABLE_SIZE] = U8_TO_ULAW;
+static const uint8_t u8_to_alaw[G711_TABLE_SIZE] = U8_TO_ALAW;
+
+/* Helper function to write one sample value to a buffer. */
+static void
+local_pcm_write(uint8_t *dst, intpcm_t value, uint32_t format)
+{
+ switch (format) {
+ case AFMT_S8:
+ _PCM_WRITE_S8_NE(dst, value);
+ break;
+ case AFMT_U8:
+ _PCM_WRITE_U8_NE(dst, value);
+ break;
+ case AFMT_S16_LE:
+ _PCM_WRITE_S16_LE(dst, value);
+ break;
+ case AFMT_S16_BE:
+ _PCM_WRITE_S16_BE(dst, value);
+ break;
+ case AFMT_U16_LE:
+ _PCM_WRITE_U16_LE(dst, value);
+ break;
+ case AFMT_U16_BE:
+ _PCM_WRITE_U16_BE(dst, value);
+ break;
+ case AFMT_S24_LE:
+ _PCM_WRITE_S24_LE(dst, value);
+ break;
+ case AFMT_S24_BE:
+ _PCM_WRITE_S24_BE(dst, value);
+ break;
+ case AFMT_U24_LE:
+ _PCM_WRITE_U24_LE(dst, value);
+ break;
+ case AFMT_U24_BE:
+ _PCM_WRITE_U24_BE(dst, value);
+ break;
+ case AFMT_S32_LE:
+ _PCM_WRITE_S32_LE(dst, value);
+ break;
+ case AFMT_S32_BE:
+ _PCM_WRITE_S32_BE(dst, value);
+ break;
+ case AFMT_U32_LE:
+ _PCM_WRITE_U32_LE(dst, value);
+ break;
+ case AFMT_U32_BE:
+ _PCM_WRITE_U32_BE(dst, value);
+ break;
+ case AFMT_MU_LAW:
+ *dst = _INTPCM_TO_G711(u8_to_ulaw, value);
+ break;
+ case AFMT_A_LAW:
+ *dst = _INTPCM_TO_G711(u8_to_alaw, value);
+ break;
+ default:
+ value = 0;
+ }
+}
+
+/* Helper function to write one calculation sample value to a buffer. */
+static void
+local_pcm_write_calc(uint8_t *dst, intpcm_t value, uint32_t format)
+{
+ switch (format) {
+ case AFMT_S8:
+ PCM_WRITE_S8_NE(dst, value);
+ break;
+ case AFMT_U8:
+ PCM_WRITE_U8_NE(dst, value);
+ break;
+ case AFMT_S16_LE:
+ PCM_WRITE_S16_LE(dst, value);
+ break;
+ case AFMT_S16_BE:
+ PCM_WRITE_S16_BE(dst, value);
+ break;
+ case AFMT_U16_LE:
+ PCM_WRITE_U16_LE(dst, value);
+ break;
+ case AFMT_U16_BE:
+ PCM_WRITE_U16_BE(dst, value);
+ break;
+ case AFMT_S24_LE:
+ PCM_WRITE_S24_LE(dst, value);
+ break;
+ case AFMT_S24_BE:
+ PCM_WRITE_S24_BE(dst, value);
+ break;
+ case AFMT_U24_LE:
+ PCM_WRITE_U24_LE(dst, value);
+ break;
+ case AFMT_U24_BE:
+ PCM_WRITE_U24_BE(dst, value);
+ break;
+ case AFMT_S32_LE:
+ PCM_WRITE_S32_LE(dst, value);
+ break;
+ case AFMT_S32_BE:
+ PCM_WRITE_S32_BE(dst, value);
+ break;
+ case AFMT_U32_LE:
+ PCM_WRITE_U32_LE(dst, value);
+ break;
+ case AFMT_U32_BE:
+ PCM_WRITE_U32_BE(dst, value);
+ break;
+ case AFMT_MU_LAW:
+ *dst = _INTPCM_TO_G711(u8_to_ulaw, value);
+ break;
+ case AFMT_A_LAW:
+ *dst = _INTPCM_TO_G711(u8_to_alaw, value);
+ break;
+ default:
+ value = 0;
+ }
+}
+
+/* Helper function to write one normalized sample to a buffer. */
+static void
+local_pcm_write_norm(uint8_t *dst, intpcm_t value, uint32_t format)
+{
+ local_pcm_write(dst, value >> (32 - AFMT_BIT(format)), format);
+}
+
+ATF_TC(pcm_read);
+ATF_TC_HEAD(pcm_read, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Read and verify different pcm sample formats.");
+}
+ATF_TC_BODY(pcm_read, tc)
+{
+ const struct afmt_test_data *test;
+ uint8_t src[4];
+ intpcm_t expected, result;
+ size_t i;
+
+ for (i = 0; i < nitems(afmt_tests); i++) {
+ test = &afmt_tests[i];
+
+ /* Copy byte representation, fill with distinctive pattern. */
+ memset(src, 0x66, sizeof(src));
+ memcpy(src, test->buffer, test->size);
+
+ /* Read sample at format magnitude. */
+ expected = test->value;
+ result = local_pcm_read(src, test->format);
+ ATF_CHECK_MSG(result == expected,
+ "pcm_read[\"%s\"].value: expected=0x%08x, result=0x%08x",
+ test->label, expected, result);
+
+ /* Read sample at format magnitude, for calculations. */
+ expected = local_calc_limit(test->value, test->size * 8);
+ result = local_pcm_read_calc(src, test->format);
+ ATF_CHECK_MSG(result == expected,
+ "pcm_read[\"%s\"].calc: expected=0x%08x, result=0x%08x",
+ test->label, expected, result);
+
+ /* Read sample at full 32 bit magnitude. */
+ expected = local_normalize(test->value, test->size * 8, 32);
+ result = local_pcm_read_norm(src, test->format);
+ ATF_CHECK_MSG(result == expected,
+ "pcm_read[\"%s\"].norm: expected=0x%08x, result=0x%08x",
+ test->label, expected, result);
+ }
+}
+
+ATF_TC(pcm_write);
+ATF_TC_HEAD(pcm_write, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Write and verify different pcm sample formats.");
+}
+ATF_TC_BODY(pcm_write, tc)
+{
+ const struct afmt_test_data *test;
+ uint8_t expected[4];
+ uint8_t dst[4];
+ intpcm_t value;
+ size_t i;
+
+ for (i = 0; i < nitems(afmt_tests); i++) {
+ test = &afmt_tests[i];
+
+ /* Write sample of format specific magnitude. */
+ memcpy(expected, test->buffer, sizeof(expected));
+ memset(dst, 0x00, sizeof(dst));
+ value = test->value;
+ local_pcm_write(dst, value, test->format);
+ ATF_CHECK_MSG(memcmp(dst, expected, sizeof(dst)) == 0,
+ "pcm_write[\"%s\"].value: "
+ "expected={0x%02x, 0x%02x, 0x%02x, 0x%02x}, "
+ "result={0x%02x, 0x%02x, 0x%02x, 0x%02x}, ", test->label,
+ expected[0], expected[1], expected[2], expected[3],
+ dst[0], dst[1], dst[2], dst[3]);
+
+ /* Write sample of format specific, calculation magnitude. */
+ memcpy(expected, test->buffer, sizeof(expected));
+ memset(dst, 0x00, sizeof(dst));
+ value = local_calc_limit(test->value, test->size * 8);
+ if (value != test->value) {
+ /*
+ * 32 bit sample was reduced to 24 bit resolution
+ * for calculation, least significant byte is lost.
+ */
+ if (test->format & AFMT_BIGENDIAN)
+ expected[3] = 0x00;
+ else
+ expected[0] = 0x00;
+ }
+ local_pcm_write_calc(dst, value, test->format);
+ ATF_CHECK_MSG(memcmp(dst, expected, sizeof(dst)) == 0,
+ "pcm_write[\"%s\"].value: "
+ "expected={0x%02x, 0x%02x, 0x%02x, 0x%02x}, "
+ "result={0x%02x, 0x%02x, 0x%02x, 0x%02x}, ", test->label,
+ expected[0], expected[1], expected[2], expected[3],
+ dst[0], dst[1], dst[2], dst[3]);
+
+ /* Write normalized sample of full 32 bit magnitude. */
+ memcpy(expected, test->buffer, sizeof(expected));
+ memset(dst, 0x00, sizeof(dst));
+ value = local_normalize(test->value, test->size * 8, 32);
+ local_pcm_write_norm(dst, value, test->format);
+ ATF_CHECK_MSG(memcmp(dst, expected, sizeof(dst)) == 0,
+ "pcm_write[\"%s\"].norm: "
+ "expected={0x%02x, 0x%02x, 0x%02x, 0x%02x}, "
+ "result={0x%02x, 0x%02x, 0x%02x, 0x%02x}, ", test->label,
+ expected[0], expected[1], expected[2], expected[3],
+ dst[0], dst[1], dst[2], dst[3]);
+ }
+}
+
+ATF_TC(pcm_format_bits);
+ATF_TC_HEAD(pcm_format_bits, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Verify bit width of different pcm sample formats.");
+}
+ATF_TC_BODY(pcm_format_bits, tc)
+{
+ const struct afmt_test_data *test;
+ size_t bits;
+ size_t i;
+
+ for (i = 0; i < nitems(afmt_tests); i++) {
+ test = &afmt_tests[i];
+
+ /* Check bit width determined for given sample format. */
+ bits = AFMT_BIT(test->format);
+ ATF_CHECK_MSG(bits == test->size * 8,
+ "format_bits[%zu].size: expected=%zu, result=%zu",
+ i, test->size * 8, bits);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, pcm_read);
+ ATF_TP_ADD_TC(tp, pcm_write);
+ ATF_TP_ADD_TC(tp, pcm_format_bits);
+
+ return atf_no_error();
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Feb 7, 2:16 PM (5 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16500025
Default Alt Text
D48330.diff (19 KB)
Attached To
Mode
D48330: sound: Unit test the pcm sample read and write macros
Attached
Detach File
Event Timeline
Log In to Comment