127ef5d48SFlorian Walpen /*- 227ef5d48SFlorian Walpen * Copyright (c) 2025 Florian Walpen 327ef5d48SFlorian Walpen * 427ef5d48SFlorian Walpen * SPDX-License-Identifier: BSD-2-Clause 527ef5d48SFlorian Walpen */ 627ef5d48SFlorian Walpen 727ef5d48SFlorian Walpen /* 827ef5d48SFlorian Walpen * These tests exercise conversion functions of the sound module, used to read 927ef5d48SFlorian Walpen * pcm samples from a buffer, and write pcm samples to a buffer. The test cases 1027ef5d48SFlorian Walpen * are non-exhaustive, but should detect systematic errors in conversion of the 1127ef5d48SFlorian Walpen * various sample formats supported. In particular, the test cases establish 1227ef5d48SFlorian Walpen * correctness independent of the machine's endianness, making them suitable to 1327ef5d48SFlorian Walpen * check for architecture-specific problems. 1427ef5d48SFlorian Walpen */ 1527ef5d48SFlorian Walpen 1627ef5d48SFlorian Walpen #include <sys/types.h> 1727ef5d48SFlorian Walpen #include <sys/soundcard.h> 1827ef5d48SFlorian Walpen 1927ef5d48SFlorian Walpen #include <atf-c.h> 2027ef5d48SFlorian Walpen #include <stdio.h> 2127ef5d48SFlorian Walpen #include <string.h> 2227ef5d48SFlorian Walpen 2327ef5d48SFlorian Walpen #include <dev/sound/pcm/sound.h> 2427ef5d48SFlorian Walpen #include <dev/sound/pcm/pcm.h> 2527ef5d48SFlorian Walpen #include <dev/sound/pcm/g711.h> 2627ef5d48SFlorian Walpen 2727ef5d48SFlorian Walpen /* Generic test data, with buffer content matching the sample values. */ 28f6631da0SChristos Margiolis static struct afmt_test_data { 2927ef5d48SFlorian Walpen const char *label; 3027ef5d48SFlorian Walpen uint8_t buffer[4]; 3127ef5d48SFlorian Walpen size_t size; 3227ef5d48SFlorian Walpen int format; 3327ef5d48SFlorian Walpen intpcm_t value; 3427ef5d48SFlorian Walpen _Static_assert((sizeof(intpcm_t) == 4), 3527ef5d48SFlorian Walpen "Test data assumes 32bit, adjust negative values to new size."); 36f6631da0SChristos Margiolis } const afmt_tests[] = { 3727ef5d48SFlorian Walpen /* 8 bit sample formats. */ 3827ef5d48SFlorian Walpen {"s8_1", {0x01, 0x00, 0x00, 0x00}, 1, AFMT_S8, 0x00000001}, 3927ef5d48SFlorian Walpen {"s8_2", {0x81, 0x00, 0x00, 0x00}, 1, AFMT_S8, 0xffffff81}, 4027ef5d48SFlorian Walpen {"u8_1", {0x01, 0x00, 0x00, 0x00}, 1, AFMT_U8, 0xffffff81}, 4127ef5d48SFlorian Walpen {"u8_2", {0x81, 0x00, 0x00, 0x00}, 1, AFMT_U8, 0x00000001}, 4227ef5d48SFlorian Walpen 4327ef5d48SFlorian Walpen /* 16 bit sample formats. */ 4427ef5d48SFlorian Walpen {"s16le_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_S16_LE, 0x00000201}, 4527ef5d48SFlorian Walpen {"s16le_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_S16_LE, 0xffff8281}, 4627ef5d48SFlorian Walpen {"s16be_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_S16_BE, 0x00000102}, 4727ef5d48SFlorian Walpen {"s16be_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_S16_BE, 0xffff8182}, 4827ef5d48SFlorian Walpen {"u16le_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_U16_LE, 0xffff8201}, 4927ef5d48SFlorian Walpen {"u16le_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_U16_LE, 0x00000281}, 5027ef5d48SFlorian Walpen {"u16be_1", {0x01, 0x02, 0x00, 0x00}, 2, AFMT_U16_BE, 0xffff8102}, 5127ef5d48SFlorian Walpen {"u16be_2", {0x81, 0x82, 0x00, 0x00}, 2, AFMT_U16_BE, 0x00000182}, 5227ef5d48SFlorian Walpen 5327ef5d48SFlorian Walpen /* 24 bit sample formats. */ 5427ef5d48SFlorian Walpen {"s24le_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_S24_LE, 0x00030201}, 5527ef5d48SFlorian Walpen {"s24le_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_S24_LE, 0xff838281}, 5627ef5d48SFlorian Walpen {"s24be_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_S24_BE, 0x00010203}, 5727ef5d48SFlorian Walpen {"s24be_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_S24_BE, 0xff818283}, 5827ef5d48SFlorian Walpen {"u24le_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_U24_LE, 0xff830201}, 5927ef5d48SFlorian Walpen {"u24le_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_U24_LE, 0x00038281}, 6027ef5d48SFlorian Walpen {"u24be_1", {0x01, 0x02, 0x03, 0x00}, 3, AFMT_U24_BE, 0xff810203}, 6127ef5d48SFlorian Walpen {"u24be_2", {0x81, 0x82, 0x83, 0x00}, 3, AFMT_U24_BE, 0x00018283}, 6227ef5d48SFlorian Walpen 6327ef5d48SFlorian Walpen /* 32 bit sample formats. */ 6427ef5d48SFlorian Walpen {"s32le_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_S32_LE, 0x04030201}, 6527ef5d48SFlorian Walpen {"s32le_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_S32_LE, 0x84838281}, 6627ef5d48SFlorian Walpen {"s32be_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_S32_BE, 0x01020304}, 6727ef5d48SFlorian Walpen {"s32be_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_S32_BE, 0x81828384}, 6827ef5d48SFlorian Walpen {"u32le_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_U32_LE, 0x84030201}, 6927ef5d48SFlorian Walpen {"u32le_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_U32_LE, 0x04838281}, 7027ef5d48SFlorian Walpen {"u32be_1", {0x01, 0x02, 0x03, 0x04}, 4, AFMT_U32_BE, 0x81020304}, 7127ef5d48SFlorian Walpen {"u32be_2", {0x81, 0x82, 0x83, 0x84}, 4, AFMT_U32_BE, 0x01828384}, 7227ef5d48SFlorian Walpen 7327ef5d48SFlorian Walpen /* u-law and A-law sample formats. */ 7427ef5d48SFlorian Walpen {"mulaw_1", {0x01, 0x00, 0x00, 0x00}, 1, AFMT_MU_LAW, 0xffffff87}, 7527ef5d48SFlorian Walpen {"mulaw_2", {0x81, 0x00, 0x00, 0x00}, 1, AFMT_MU_LAW, 0x00000079}, 7627ef5d48SFlorian Walpen {"alaw_1", {0x2a, 0x00, 0x00, 0x00}, 1, AFMT_A_LAW, 0xffffff83}, 7727ef5d48SFlorian Walpen {"alaw_2", {0xab, 0x00, 0x00, 0x00}, 1, AFMT_A_LAW, 0x00000079} 7827ef5d48SFlorian Walpen }; 7927ef5d48SFlorian Walpen 8027ef5d48SFlorian Walpen /* Normalize sample values in strictly correct (but slow) c. */ 8127ef5d48SFlorian Walpen static intpcm_t 8227ef5d48SFlorian Walpen local_normalize(intpcm_t value, int val_bits, int norm_bits) 8327ef5d48SFlorian Walpen { 8427ef5d48SFlorian Walpen /* Avoid undefined or implementation defined behavior. */ 8527ef5d48SFlorian Walpen if (val_bits < norm_bits) 8627ef5d48SFlorian Walpen /* Multiply instead of left shift (value may be negative). */ 8727ef5d48SFlorian Walpen return (value * (1 << (norm_bits - val_bits))); 8827ef5d48SFlorian Walpen else if (val_bits > norm_bits) 8927ef5d48SFlorian Walpen /* Divide instead of right shift (value may be negative). */ 9027ef5d48SFlorian Walpen return (value / (1 << (val_bits - norm_bits))); 9127ef5d48SFlorian Walpen return value; 9227ef5d48SFlorian Walpen } 9327ef5d48SFlorian Walpen 9427ef5d48SFlorian Walpen /* Restrict magnitude of sample value to 24bit for 32bit calculations. */ 9527ef5d48SFlorian Walpen static intpcm_t 9627ef5d48SFlorian Walpen local_calc_limit(intpcm_t value, int val_bits) 9727ef5d48SFlorian Walpen { 98*e02b579bSFlorian Walpen /* 99*e02b579bSFlorian Walpen * When intpcm32_t is defined to be 32bit, calculations for mixing and 100*e02b579bSFlorian Walpen * volume changes use 32bit integers instead of 64bit. To get some 101*e02b579bSFlorian Walpen * headroom for calculations, 32bit sample values are restricted to 102*e02b579bSFlorian Walpen * 24bit magnitude in that case. Also avoid implementation defined 103*e02b579bSFlorian Walpen * behavior here. 104*e02b579bSFlorian Walpen */ 105*e02b579bSFlorian Walpen if (sizeof(intpcm32_t) == (32 / 8) && val_bits == 32) 10627ef5d48SFlorian Walpen /* Divide instead of right shift (value may be negative). */ 10727ef5d48SFlorian Walpen return (value / (1 << 8)); 10827ef5d48SFlorian Walpen return value; 10927ef5d48SFlorian Walpen } 11027ef5d48SFlorian Walpen 11127ef5d48SFlorian Walpen /* Lookup tables to read u-law and A-law sample formats. */ 11227ef5d48SFlorian Walpen static const uint8_t ulaw_to_u8[G711_TABLE_SIZE] = ULAW_TO_U8; 11327ef5d48SFlorian Walpen static const uint8_t alaw_to_u8[G711_TABLE_SIZE] = ALAW_TO_U8; 11427ef5d48SFlorian Walpen 11527ef5d48SFlorian Walpen /* Helper function to read one sample value from a buffer. */ 11627ef5d48SFlorian Walpen static intpcm_t 11727ef5d48SFlorian Walpen local_pcm_read(uint8_t *src, uint32_t format) 11827ef5d48SFlorian Walpen { 11927ef5d48SFlorian Walpen intpcm_t value; 12027ef5d48SFlorian Walpen 12127ef5d48SFlorian Walpen switch (format) { 12227ef5d48SFlorian Walpen case AFMT_S8: 12327ef5d48SFlorian Walpen value = _PCM_READ_S8_NE(src); 12427ef5d48SFlorian Walpen break; 12527ef5d48SFlorian Walpen case AFMT_U8: 12627ef5d48SFlorian Walpen value = _PCM_READ_U8_NE(src); 12727ef5d48SFlorian Walpen break; 12827ef5d48SFlorian Walpen case AFMT_S16_LE: 12927ef5d48SFlorian Walpen value = _PCM_READ_S16_LE(src); 13027ef5d48SFlorian Walpen break; 13127ef5d48SFlorian Walpen case AFMT_S16_BE: 13227ef5d48SFlorian Walpen value = _PCM_READ_S16_BE(src); 13327ef5d48SFlorian Walpen break; 13427ef5d48SFlorian Walpen case AFMT_U16_LE: 13527ef5d48SFlorian Walpen value = _PCM_READ_U16_LE(src); 13627ef5d48SFlorian Walpen break; 13727ef5d48SFlorian Walpen case AFMT_U16_BE: 13827ef5d48SFlorian Walpen value = _PCM_READ_U16_BE(src); 13927ef5d48SFlorian Walpen break; 14027ef5d48SFlorian Walpen case AFMT_S24_LE: 14127ef5d48SFlorian Walpen value = _PCM_READ_S24_LE(src); 14227ef5d48SFlorian Walpen break; 14327ef5d48SFlorian Walpen case AFMT_S24_BE: 14427ef5d48SFlorian Walpen value = _PCM_READ_S24_BE(src); 14527ef5d48SFlorian Walpen break; 14627ef5d48SFlorian Walpen case AFMT_U24_LE: 14727ef5d48SFlorian Walpen value = _PCM_READ_U24_LE(src); 14827ef5d48SFlorian Walpen break; 14927ef5d48SFlorian Walpen case AFMT_U24_BE: 15027ef5d48SFlorian Walpen value = _PCM_READ_U24_BE(src); 15127ef5d48SFlorian Walpen break; 15227ef5d48SFlorian Walpen case AFMT_S32_LE: 15327ef5d48SFlorian Walpen value = _PCM_READ_S32_LE(src); 15427ef5d48SFlorian Walpen break; 15527ef5d48SFlorian Walpen case AFMT_S32_BE: 15627ef5d48SFlorian Walpen value = _PCM_READ_S32_BE(src); 15727ef5d48SFlorian Walpen break; 15827ef5d48SFlorian Walpen case AFMT_U32_LE: 15927ef5d48SFlorian Walpen value = _PCM_READ_U32_LE(src); 16027ef5d48SFlorian Walpen break; 16127ef5d48SFlorian Walpen case AFMT_U32_BE: 16227ef5d48SFlorian Walpen value = _PCM_READ_U32_BE(src); 16327ef5d48SFlorian Walpen break; 16427ef5d48SFlorian Walpen case AFMT_MU_LAW: 16527ef5d48SFlorian Walpen value = _G711_TO_INTPCM(ulaw_to_u8, *src); 16627ef5d48SFlorian Walpen break; 16727ef5d48SFlorian Walpen case AFMT_A_LAW: 16827ef5d48SFlorian Walpen value = _G711_TO_INTPCM(alaw_to_u8, *src); 16927ef5d48SFlorian Walpen break; 17027ef5d48SFlorian Walpen default: 17127ef5d48SFlorian Walpen value = 0; 17227ef5d48SFlorian Walpen } 17327ef5d48SFlorian Walpen 17427ef5d48SFlorian Walpen return (value); 17527ef5d48SFlorian Walpen } 17627ef5d48SFlorian Walpen 17727ef5d48SFlorian Walpen /* Helper function to read one sample value from a buffer for calculations. */ 17827ef5d48SFlorian Walpen static intpcm_t 17927ef5d48SFlorian Walpen local_pcm_read_calc(uint8_t *src, uint32_t format) 18027ef5d48SFlorian Walpen { 18127ef5d48SFlorian Walpen intpcm_t value; 18227ef5d48SFlorian Walpen 18327ef5d48SFlorian Walpen switch (format) { 18427ef5d48SFlorian Walpen case AFMT_S8: 18527ef5d48SFlorian Walpen value = PCM_READ_S8_NE(src); 18627ef5d48SFlorian Walpen break; 18727ef5d48SFlorian Walpen case AFMT_U8: 18827ef5d48SFlorian Walpen value = PCM_READ_U8_NE(src); 18927ef5d48SFlorian Walpen break; 19027ef5d48SFlorian Walpen case AFMT_S16_LE: 19127ef5d48SFlorian Walpen value = PCM_READ_S16_LE(src); 19227ef5d48SFlorian Walpen break; 19327ef5d48SFlorian Walpen case AFMT_S16_BE: 19427ef5d48SFlorian Walpen value = PCM_READ_S16_BE(src); 19527ef5d48SFlorian Walpen break; 19627ef5d48SFlorian Walpen case AFMT_U16_LE: 19727ef5d48SFlorian Walpen value = PCM_READ_U16_LE(src); 19827ef5d48SFlorian Walpen break; 19927ef5d48SFlorian Walpen case AFMT_U16_BE: 20027ef5d48SFlorian Walpen value = PCM_READ_U16_BE(src); 20127ef5d48SFlorian Walpen break; 20227ef5d48SFlorian Walpen case AFMT_S24_LE: 20327ef5d48SFlorian Walpen value = PCM_READ_S24_LE(src); 20427ef5d48SFlorian Walpen break; 20527ef5d48SFlorian Walpen case AFMT_S24_BE: 20627ef5d48SFlorian Walpen value = PCM_READ_S24_BE(src); 20727ef5d48SFlorian Walpen break; 20827ef5d48SFlorian Walpen case AFMT_U24_LE: 20927ef5d48SFlorian Walpen value = PCM_READ_U24_LE(src); 21027ef5d48SFlorian Walpen break; 21127ef5d48SFlorian Walpen case AFMT_U24_BE: 21227ef5d48SFlorian Walpen value = PCM_READ_U24_BE(src); 21327ef5d48SFlorian Walpen break; 21427ef5d48SFlorian Walpen case AFMT_S32_LE: 21527ef5d48SFlorian Walpen value = PCM_READ_S32_LE(src); 21627ef5d48SFlorian Walpen break; 21727ef5d48SFlorian Walpen case AFMT_S32_BE: 21827ef5d48SFlorian Walpen value = PCM_READ_S32_BE(src); 21927ef5d48SFlorian Walpen break; 22027ef5d48SFlorian Walpen case AFMT_U32_LE: 22127ef5d48SFlorian Walpen value = PCM_READ_U32_LE(src); 22227ef5d48SFlorian Walpen break; 22327ef5d48SFlorian Walpen case AFMT_U32_BE: 22427ef5d48SFlorian Walpen value = PCM_READ_U32_BE(src); 22527ef5d48SFlorian Walpen break; 22627ef5d48SFlorian Walpen case AFMT_MU_LAW: 22727ef5d48SFlorian Walpen value = _G711_TO_INTPCM(ulaw_to_u8, *src); 22827ef5d48SFlorian Walpen break; 22927ef5d48SFlorian Walpen case AFMT_A_LAW: 23027ef5d48SFlorian Walpen value = _G711_TO_INTPCM(alaw_to_u8, *src); 23127ef5d48SFlorian Walpen break; 23227ef5d48SFlorian Walpen default: 23327ef5d48SFlorian Walpen value = 0; 23427ef5d48SFlorian Walpen } 23527ef5d48SFlorian Walpen 23627ef5d48SFlorian Walpen return (value); 23727ef5d48SFlorian Walpen } 23827ef5d48SFlorian Walpen 23927ef5d48SFlorian Walpen /* Helper function to read one normalized sample from a buffer. */ 24027ef5d48SFlorian Walpen static intpcm_t 24127ef5d48SFlorian Walpen local_pcm_read_norm(uint8_t *src, uint32_t format) 24227ef5d48SFlorian Walpen { 24327ef5d48SFlorian Walpen intpcm_t value; 24427ef5d48SFlorian Walpen 24527ef5d48SFlorian Walpen value = local_pcm_read(src, format); 24627ef5d48SFlorian Walpen value <<= (32 - AFMT_BIT(format)); 24727ef5d48SFlorian Walpen return (value); 24827ef5d48SFlorian Walpen } 24927ef5d48SFlorian Walpen 25027ef5d48SFlorian Walpen /* Lookup tables to write u-law and A-law sample formats. */ 25127ef5d48SFlorian Walpen static const uint8_t u8_to_ulaw[G711_TABLE_SIZE] = U8_TO_ULAW; 25227ef5d48SFlorian Walpen static const uint8_t u8_to_alaw[G711_TABLE_SIZE] = U8_TO_ALAW; 25327ef5d48SFlorian Walpen 25427ef5d48SFlorian Walpen /* Helper function to write one sample value to a buffer. */ 25527ef5d48SFlorian Walpen static void 25627ef5d48SFlorian Walpen local_pcm_write(uint8_t *dst, intpcm_t value, uint32_t format) 25727ef5d48SFlorian Walpen { 25827ef5d48SFlorian Walpen switch (format) { 25927ef5d48SFlorian Walpen case AFMT_S8: 26027ef5d48SFlorian Walpen _PCM_WRITE_S8_NE(dst, value); 26127ef5d48SFlorian Walpen break; 26227ef5d48SFlorian Walpen case AFMT_U8: 26327ef5d48SFlorian Walpen _PCM_WRITE_U8_NE(dst, value); 26427ef5d48SFlorian Walpen break; 26527ef5d48SFlorian Walpen case AFMT_S16_LE: 26627ef5d48SFlorian Walpen _PCM_WRITE_S16_LE(dst, value); 26727ef5d48SFlorian Walpen break; 26827ef5d48SFlorian Walpen case AFMT_S16_BE: 26927ef5d48SFlorian Walpen _PCM_WRITE_S16_BE(dst, value); 27027ef5d48SFlorian Walpen break; 27127ef5d48SFlorian Walpen case AFMT_U16_LE: 27227ef5d48SFlorian Walpen _PCM_WRITE_U16_LE(dst, value); 27327ef5d48SFlorian Walpen break; 27427ef5d48SFlorian Walpen case AFMT_U16_BE: 27527ef5d48SFlorian Walpen _PCM_WRITE_U16_BE(dst, value); 27627ef5d48SFlorian Walpen break; 27727ef5d48SFlorian Walpen case AFMT_S24_LE: 27827ef5d48SFlorian Walpen _PCM_WRITE_S24_LE(dst, value); 27927ef5d48SFlorian Walpen break; 28027ef5d48SFlorian Walpen case AFMT_S24_BE: 28127ef5d48SFlorian Walpen _PCM_WRITE_S24_BE(dst, value); 28227ef5d48SFlorian Walpen break; 28327ef5d48SFlorian Walpen case AFMT_U24_LE: 28427ef5d48SFlorian Walpen _PCM_WRITE_U24_LE(dst, value); 28527ef5d48SFlorian Walpen break; 28627ef5d48SFlorian Walpen case AFMT_U24_BE: 28727ef5d48SFlorian Walpen _PCM_WRITE_U24_BE(dst, value); 28827ef5d48SFlorian Walpen break; 28927ef5d48SFlorian Walpen case AFMT_S32_LE: 29027ef5d48SFlorian Walpen _PCM_WRITE_S32_LE(dst, value); 29127ef5d48SFlorian Walpen break; 29227ef5d48SFlorian Walpen case AFMT_S32_BE: 29327ef5d48SFlorian Walpen _PCM_WRITE_S32_BE(dst, value); 29427ef5d48SFlorian Walpen break; 29527ef5d48SFlorian Walpen case AFMT_U32_LE: 29627ef5d48SFlorian Walpen _PCM_WRITE_U32_LE(dst, value); 29727ef5d48SFlorian Walpen break; 29827ef5d48SFlorian Walpen case AFMT_U32_BE: 29927ef5d48SFlorian Walpen _PCM_WRITE_U32_BE(dst, value); 30027ef5d48SFlorian Walpen break; 30127ef5d48SFlorian Walpen case AFMT_MU_LAW: 30227ef5d48SFlorian Walpen *dst = _INTPCM_TO_G711(u8_to_ulaw, value); 30327ef5d48SFlorian Walpen break; 30427ef5d48SFlorian Walpen case AFMT_A_LAW: 30527ef5d48SFlorian Walpen *dst = _INTPCM_TO_G711(u8_to_alaw, value); 30627ef5d48SFlorian Walpen break; 30727ef5d48SFlorian Walpen default: 30827ef5d48SFlorian Walpen value = 0; 30927ef5d48SFlorian Walpen } 31027ef5d48SFlorian Walpen } 31127ef5d48SFlorian Walpen 31227ef5d48SFlorian Walpen /* Helper function to write one calculation sample value to a buffer. */ 31327ef5d48SFlorian Walpen static void 31427ef5d48SFlorian Walpen local_pcm_write_calc(uint8_t *dst, intpcm_t value, uint32_t format) 31527ef5d48SFlorian Walpen { 31627ef5d48SFlorian Walpen switch (format) { 31727ef5d48SFlorian Walpen case AFMT_S8: 31827ef5d48SFlorian Walpen PCM_WRITE_S8_NE(dst, value); 31927ef5d48SFlorian Walpen break; 32027ef5d48SFlorian Walpen case AFMT_U8: 32127ef5d48SFlorian Walpen PCM_WRITE_U8_NE(dst, value); 32227ef5d48SFlorian Walpen break; 32327ef5d48SFlorian Walpen case AFMT_S16_LE: 32427ef5d48SFlorian Walpen PCM_WRITE_S16_LE(dst, value); 32527ef5d48SFlorian Walpen break; 32627ef5d48SFlorian Walpen case AFMT_S16_BE: 32727ef5d48SFlorian Walpen PCM_WRITE_S16_BE(dst, value); 32827ef5d48SFlorian Walpen break; 32927ef5d48SFlorian Walpen case AFMT_U16_LE: 33027ef5d48SFlorian Walpen PCM_WRITE_U16_LE(dst, value); 33127ef5d48SFlorian Walpen break; 33227ef5d48SFlorian Walpen case AFMT_U16_BE: 33327ef5d48SFlorian Walpen PCM_WRITE_U16_BE(dst, value); 33427ef5d48SFlorian Walpen break; 33527ef5d48SFlorian Walpen case AFMT_S24_LE: 33627ef5d48SFlorian Walpen PCM_WRITE_S24_LE(dst, value); 33727ef5d48SFlorian Walpen break; 33827ef5d48SFlorian Walpen case AFMT_S24_BE: 33927ef5d48SFlorian Walpen PCM_WRITE_S24_BE(dst, value); 34027ef5d48SFlorian Walpen break; 34127ef5d48SFlorian Walpen case AFMT_U24_LE: 34227ef5d48SFlorian Walpen PCM_WRITE_U24_LE(dst, value); 34327ef5d48SFlorian Walpen break; 34427ef5d48SFlorian Walpen case AFMT_U24_BE: 34527ef5d48SFlorian Walpen PCM_WRITE_U24_BE(dst, value); 34627ef5d48SFlorian Walpen break; 34727ef5d48SFlorian Walpen case AFMT_S32_LE: 34827ef5d48SFlorian Walpen PCM_WRITE_S32_LE(dst, value); 34927ef5d48SFlorian Walpen break; 35027ef5d48SFlorian Walpen case AFMT_S32_BE: 35127ef5d48SFlorian Walpen PCM_WRITE_S32_BE(dst, value); 35227ef5d48SFlorian Walpen break; 35327ef5d48SFlorian Walpen case AFMT_U32_LE: 35427ef5d48SFlorian Walpen PCM_WRITE_U32_LE(dst, value); 35527ef5d48SFlorian Walpen break; 35627ef5d48SFlorian Walpen case AFMT_U32_BE: 35727ef5d48SFlorian Walpen PCM_WRITE_U32_BE(dst, value); 35827ef5d48SFlorian Walpen break; 35927ef5d48SFlorian Walpen case AFMT_MU_LAW: 36027ef5d48SFlorian Walpen *dst = _INTPCM_TO_G711(u8_to_ulaw, value); 36127ef5d48SFlorian Walpen break; 36227ef5d48SFlorian Walpen case AFMT_A_LAW: 36327ef5d48SFlorian Walpen *dst = _INTPCM_TO_G711(u8_to_alaw, value); 36427ef5d48SFlorian Walpen break; 36527ef5d48SFlorian Walpen default: 36627ef5d48SFlorian Walpen value = 0; 36727ef5d48SFlorian Walpen } 36827ef5d48SFlorian Walpen } 36927ef5d48SFlorian Walpen 37027ef5d48SFlorian Walpen /* Helper function to write one normalized sample to a buffer. */ 37127ef5d48SFlorian Walpen static void 37227ef5d48SFlorian Walpen local_pcm_write_norm(uint8_t *dst, intpcm_t value, uint32_t format) 37327ef5d48SFlorian Walpen { 37427ef5d48SFlorian Walpen local_pcm_write(dst, value >> (32 - AFMT_BIT(format)), format); 37527ef5d48SFlorian Walpen } 37627ef5d48SFlorian Walpen 37727ef5d48SFlorian Walpen ATF_TC(pcm_read); 37827ef5d48SFlorian Walpen ATF_TC_HEAD(pcm_read, tc) 37927ef5d48SFlorian Walpen { 38027ef5d48SFlorian Walpen atf_tc_set_md_var(tc, "descr", 38127ef5d48SFlorian Walpen "Read and verify different pcm sample formats."); 38227ef5d48SFlorian Walpen } 38327ef5d48SFlorian Walpen ATF_TC_BODY(pcm_read, tc) 38427ef5d48SFlorian Walpen { 38527ef5d48SFlorian Walpen const struct afmt_test_data *test; 38627ef5d48SFlorian Walpen uint8_t src[4]; 38727ef5d48SFlorian Walpen intpcm_t expected, result; 38827ef5d48SFlorian Walpen size_t i; 38927ef5d48SFlorian Walpen 39027ef5d48SFlorian Walpen for (i = 0; i < nitems(afmt_tests); i++) { 39127ef5d48SFlorian Walpen test = &afmt_tests[i]; 39227ef5d48SFlorian Walpen 39327ef5d48SFlorian Walpen /* Copy byte representation, fill with distinctive pattern. */ 39427ef5d48SFlorian Walpen memset(src, 0x66, sizeof(src)); 39527ef5d48SFlorian Walpen memcpy(src, test->buffer, test->size); 39627ef5d48SFlorian Walpen 39727ef5d48SFlorian Walpen /* Read sample at format magnitude. */ 39827ef5d48SFlorian Walpen expected = test->value; 39927ef5d48SFlorian Walpen result = local_pcm_read(src, test->format); 40027ef5d48SFlorian Walpen ATF_CHECK_MSG(result == expected, 40127ef5d48SFlorian Walpen "pcm_read[\"%s\"].value: expected=0x%08x, result=0x%08x", 40227ef5d48SFlorian Walpen test->label, expected, result); 40327ef5d48SFlorian Walpen 40427ef5d48SFlorian Walpen /* Read sample at format magnitude, for calculations. */ 40527ef5d48SFlorian Walpen expected = local_calc_limit(test->value, test->size * 8); 40627ef5d48SFlorian Walpen result = local_pcm_read_calc(src, test->format); 40727ef5d48SFlorian Walpen ATF_CHECK_MSG(result == expected, 40827ef5d48SFlorian Walpen "pcm_read[\"%s\"].calc: expected=0x%08x, result=0x%08x", 40927ef5d48SFlorian Walpen test->label, expected, result); 41027ef5d48SFlorian Walpen 41127ef5d48SFlorian Walpen /* Read sample at full 32 bit magnitude. */ 41227ef5d48SFlorian Walpen expected = local_normalize(test->value, test->size * 8, 32); 41327ef5d48SFlorian Walpen result = local_pcm_read_norm(src, test->format); 41427ef5d48SFlorian Walpen ATF_CHECK_MSG(result == expected, 41527ef5d48SFlorian Walpen "pcm_read[\"%s\"].norm: expected=0x%08x, result=0x%08x", 41627ef5d48SFlorian Walpen test->label, expected, result); 41727ef5d48SFlorian Walpen } 41827ef5d48SFlorian Walpen } 41927ef5d48SFlorian Walpen 42027ef5d48SFlorian Walpen ATF_TC(pcm_write); 42127ef5d48SFlorian Walpen ATF_TC_HEAD(pcm_write, tc) 42227ef5d48SFlorian Walpen { 42327ef5d48SFlorian Walpen atf_tc_set_md_var(tc, "descr", 42427ef5d48SFlorian Walpen "Write and verify different pcm sample formats."); 42527ef5d48SFlorian Walpen } 42627ef5d48SFlorian Walpen ATF_TC_BODY(pcm_write, tc) 42727ef5d48SFlorian Walpen { 42827ef5d48SFlorian Walpen const struct afmt_test_data *test; 42927ef5d48SFlorian Walpen uint8_t expected[4]; 43027ef5d48SFlorian Walpen uint8_t dst[4]; 43127ef5d48SFlorian Walpen intpcm_t value; 43227ef5d48SFlorian Walpen size_t i; 43327ef5d48SFlorian Walpen 43427ef5d48SFlorian Walpen for (i = 0; i < nitems(afmt_tests); i++) { 43527ef5d48SFlorian Walpen test = &afmt_tests[i]; 43627ef5d48SFlorian Walpen 43727ef5d48SFlorian Walpen /* Write sample of format specific magnitude. */ 43827ef5d48SFlorian Walpen memcpy(expected, test->buffer, sizeof(expected)); 43927ef5d48SFlorian Walpen memset(dst, 0x00, sizeof(dst)); 44027ef5d48SFlorian Walpen value = test->value; 44127ef5d48SFlorian Walpen local_pcm_write(dst, value, test->format); 44227ef5d48SFlorian Walpen ATF_CHECK_MSG(memcmp(dst, expected, sizeof(dst)) == 0, 44327ef5d48SFlorian Walpen "pcm_write[\"%s\"].value: " 44427ef5d48SFlorian Walpen "expected={0x%02x, 0x%02x, 0x%02x, 0x%02x}, " 44527ef5d48SFlorian Walpen "result={0x%02x, 0x%02x, 0x%02x, 0x%02x}, ", test->label, 44627ef5d48SFlorian Walpen expected[0], expected[1], expected[2], expected[3], 44727ef5d48SFlorian Walpen dst[0], dst[1], dst[2], dst[3]); 44827ef5d48SFlorian Walpen 44927ef5d48SFlorian Walpen /* Write sample of format specific, calculation magnitude. */ 45027ef5d48SFlorian Walpen memcpy(expected, test->buffer, sizeof(expected)); 45127ef5d48SFlorian Walpen memset(dst, 0x00, sizeof(dst)); 45227ef5d48SFlorian Walpen value = local_calc_limit(test->value, test->size * 8); 45327ef5d48SFlorian Walpen if (value != test->value) { 45427ef5d48SFlorian Walpen /* 45527ef5d48SFlorian Walpen * 32 bit sample was reduced to 24 bit resolution 45627ef5d48SFlorian Walpen * for calculation, least significant byte is lost. 45727ef5d48SFlorian Walpen */ 45827ef5d48SFlorian Walpen if (test->format & AFMT_BIGENDIAN) 45927ef5d48SFlorian Walpen expected[3] = 0x00; 46027ef5d48SFlorian Walpen else 46127ef5d48SFlorian Walpen expected[0] = 0x00; 46227ef5d48SFlorian Walpen } 46327ef5d48SFlorian Walpen local_pcm_write_calc(dst, value, test->format); 46427ef5d48SFlorian Walpen ATF_CHECK_MSG(memcmp(dst, expected, sizeof(dst)) == 0, 465*e02b579bSFlorian Walpen "pcm_write[\"%s\"].calc: " 46627ef5d48SFlorian Walpen "expected={0x%02x, 0x%02x, 0x%02x, 0x%02x}, " 46727ef5d48SFlorian Walpen "result={0x%02x, 0x%02x, 0x%02x, 0x%02x}, ", test->label, 46827ef5d48SFlorian Walpen expected[0], expected[1], expected[2], expected[3], 46927ef5d48SFlorian Walpen dst[0], dst[1], dst[2], dst[3]); 47027ef5d48SFlorian Walpen 47127ef5d48SFlorian Walpen /* Write normalized sample of full 32 bit magnitude. */ 47227ef5d48SFlorian Walpen memcpy(expected, test->buffer, sizeof(expected)); 47327ef5d48SFlorian Walpen memset(dst, 0x00, sizeof(dst)); 47427ef5d48SFlorian Walpen value = local_normalize(test->value, test->size * 8, 32); 47527ef5d48SFlorian Walpen local_pcm_write_norm(dst, value, test->format); 47627ef5d48SFlorian Walpen ATF_CHECK_MSG(memcmp(dst, expected, sizeof(dst)) == 0, 47727ef5d48SFlorian Walpen "pcm_write[\"%s\"].norm: " 47827ef5d48SFlorian Walpen "expected={0x%02x, 0x%02x, 0x%02x, 0x%02x}, " 47927ef5d48SFlorian Walpen "result={0x%02x, 0x%02x, 0x%02x, 0x%02x}, ", test->label, 48027ef5d48SFlorian Walpen expected[0], expected[1], expected[2], expected[3], 48127ef5d48SFlorian Walpen dst[0], dst[1], dst[2], dst[3]); 48227ef5d48SFlorian Walpen } 48327ef5d48SFlorian Walpen } 48427ef5d48SFlorian Walpen 48527ef5d48SFlorian Walpen ATF_TC(pcm_format_bits); 48627ef5d48SFlorian Walpen ATF_TC_HEAD(pcm_format_bits, tc) 48727ef5d48SFlorian Walpen { 48827ef5d48SFlorian Walpen atf_tc_set_md_var(tc, "descr", 48927ef5d48SFlorian Walpen "Verify bit width of different pcm sample formats."); 49027ef5d48SFlorian Walpen } 49127ef5d48SFlorian Walpen ATF_TC_BODY(pcm_format_bits, tc) 49227ef5d48SFlorian Walpen { 49327ef5d48SFlorian Walpen const struct afmt_test_data *test; 49427ef5d48SFlorian Walpen size_t bits; 49527ef5d48SFlorian Walpen size_t i; 49627ef5d48SFlorian Walpen 49727ef5d48SFlorian Walpen for (i = 0; i < nitems(afmt_tests); i++) { 49827ef5d48SFlorian Walpen test = &afmt_tests[i]; 49927ef5d48SFlorian Walpen 50027ef5d48SFlorian Walpen /* Check bit width determined for given sample format. */ 50127ef5d48SFlorian Walpen bits = AFMT_BIT(test->format); 50227ef5d48SFlorian Walpen ATF_CHECK_MSG(bits == test->size * 8, 50327ef5d48SFlorian Walpen "format_bits[%zu].size: expected=%zu, result=%zu", 50427ef5d48SFlorian Walpen i, test->size * 8, bits); 50527ef5d48SFlorian Walpen } 50627ef5d48SFlorian Walpen } 50727ef5d48SFlorian Walpen 50827ef5d48SFlorian Walpen ATF_TP_ADD_TCS(tp) 50927ef5d48SFlorian Walpen { 51027ef5d48SFlorian Walpen ATF_TP_ADD_TC(tp, pcm_read); 51127ef5d48SFlorian Walpen ATF_TP_ADD_TC(tp, pcm_write); 51227ef5d48SFlorian Walpen ATF_TP_ADD_TC(tp, pcm_format_bits); 51327ef5d48SFlorian Walpen 51427ef5d48SFlorian Walpen return atf_no_error(); 51527ef5d48SFlorian Walpen } 516