/* * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "pico/stdlib.h" #include "pico/bit_ops.h" #include "pico/sample_conversion.h" typedef int (*sample_converter_fn)(int); int u16_to_u16(int s) { return (uint16_t) s; } int s16_to_u16(int s) { return (uint16_t) (s ^ 0x8000u); } int u8_to_u16(int s) { return (uint16_t) (s << 8); } int s8_to_u16(int s) { return (uint16_t) ((s << 8u) ^ 0x8000u); } int u16_to_s16(int s) { return (int16_t) (s ^ 0x8000u); } int s16_to_s16(int s) { return (int16_t) s; } int u8_to_s16(int s) { return (int16_t) ((s << 8u) ^ 0x8000u); } int s8_to_s16(int s) { return (int16_t) (s << 8u); } int u16_to_u8(int s) { return (uint8_t) (s >> 8u); } int s16_to_u8(int s) { return (uint8_t) ((s ^ 0x8000u) >> 8u); } int u8_to_u8(int s) { return (uint8_t) s; } int s8_to_u8(int s) { return (uint8_t) (s ^ 0x80); } int u16_to_s8(int s) { return (int8_t) ((s ^ 0x8000u) >> 8u); } int s16_to_s8(int s) { return (int8_t) (s >> 8u); } int u8_to_s8(int s) { return (int8_t) (s ^ 0x80); } int s8_to_s8(int s) { return (int8_t) s; } template typename Fmt::sample_t random_sample() { return (typename Fmt::sample_t) rand(); } void check_sample(int from, int expected, int actual) { if (expected != actual) { printf("Failed converting %04x to %04x (got %04x)\n", from, expected, actual); assert(false); } } template void check_conversion(sample_converter_fn converter_fn) { uint length = 256 + rand() & 0xffu; typename ToFmt::sample_t to_buffer[length * ToFmt::channel_count]; typename FromFmt::sample_t from_buffer[length * FromFmt::channel_count]; for (uint i = 0; i < length * FromFmt::channel_count; i++) { from_buffer[i] = random_sample(); } converting_copy::copy(to_buffer, from_buffer, length); if (ToFmt::channel_count == FromFmt::channel_count) { for (uint i = 0; i < length * ToFmt::channel_count; i++) { check_sample(from_buffer[i], converter_fn(from_buffer[i]), to_buffer[i]); } } else if (ToFmt::channel_count == 2 & FromFmt::channel_count == 1) { // mono -> stereo duplicates for (uint i = 0; i < length; i++) { check_sample(from_buffer[i], converter_fn(from_buffer[i]), to_buffer[i * 2]); check_sample(from_buffer[i], converter_fn(from_buffer[i]), to_buffer[i * 2 + 1]); } } else if (ToFmt::channel_count == 1 & FromFmt::channel_count == 2) { // stereo -> mono averages for (uint i = 0; i < length; i++) { // can't represent both samples check_sample(0xf00d, converter_fn((from_buffer[i * 2] + from_buffer[i * 2 + 1]) / 2), to_buffer[i]); } } else { assert(false); } } template void check_conversions(sample_converter_fn converter_fn) { // for a given format check conversions to and from check_conversion, Mono>(converter_fn); check_conversion, Mono>(converter_fn); check_conversion, Stereo>(converter_fn); check_conversion, Stereo>(converter_fn); } int main() { // On FPGA, pins 28 and 29 are connected to the VC707 board USB-UART uart_init(uart0, 115200); gpio_set_function(28, GPIO_FUNC_UART); gpio_set_function(29, GPIO_FUNC_UART); // check all permutations of supported formats check_conversions(u16_to_u16); check_conversions(u16_to_s16); check_conversions(u16_to_u8); check_conversions(u16_to_s8); check_conversions(s16_to_u16); check_conversions(s16_to_s16); check_conversions(s16_to_u8); check_conversions(s16_to_s8); check_conversions(u8_to_u16); check_conversions(u8_to_s16); check_conversions(u8_to_u8); check_conversions(u8_to_s8); check_conversions(s8_to_u16); check_conversions(s8_to_s16); check_conversions(s8_to_u8); check_conversions(s8_to_s8); printf("OK\n"); }