X-Git-Url: https://git.distorted.org.uk/~mdw/disorder/blobdiff_plain/087a9b2eaf10974c1b3025bf7d439c2371625e70..2d0a6606ee8899dfe372bbdc760fd15c14f3fceb:/libtests/t-resample.c diff --git a/libtests/t-resample.c b/libtests/t-resample.c new file mode 100644 index 0000000..2eab79a --- /dev/null +++ b/libtests/t-resample.c @@ -0,0 +1,176 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2009 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "test.h" +#include "resample.h" +#include "vector.h" + +/* Accumulate converted bytes in a dynamic string */ +static void converted(uint8_t *bytes, + size_t nbytes, + void *cd) { + struct dynstr *d = cd; + dynstr_append_bytes(d, (void *)bytes, nbytes); +} + +/* Converter wrapper */ +static uint8_t *convert(const struct resampler *rs, + const uint8_t *input, size_t input_bytes, + size_t *output_bytes) { + struct dynstr d[1]; + + dynstr_init(d); + while(input_bytes > 0) { + size_t chunk = input_bytes > 1024 ? 1024 : input_bytes; + size_t consumed = resample_convert(rs, + input, input_bytes, + input_bytes == chunk, + converted, + d); + input += consumed; + input_bytes -= consumed; + } + *output_bytes = d->nvec; + return (uint8_t *)d->vec; +} + +static const struct { + const char *description; + int input_bits; + int input_channels; + int input_rate; + int input_signed; + int input_endian; + const char *input; + size_t input_bytes; + int output_bits; + int output_channels; + int output_rate; + int output_signed; + int output_endian; + const char *output; + size_t output_bytes; +} conversions[] = { + /* Conversions that don't change the sample rate */ + { + "empty input", + 8, 1, 8000, 0, ENDIAN_LITTLE, "", 0, + 8, 1, 8000, 0, ENDIAN_LITTLE, "", 0 + }, + { + "sign flip 8-bit unsigned->signed", + 8, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x7F\x80\xFF", 4, + 8, 1, 8000, 1, ENDIAN_LITTLE, "\x80\xFF\x00\x7F", 4 + }, + { + "sign flip 8-bit signed->unsigned", + 8, 1, 8000, 1, ENDIAN_BIG, "\x80\xFF\x00\x7F", 4, + 8, 1, 8000, 0, ENDIAN_BIG, "\x00\x7F\x80\xFF", 4 + }, + { + "mono to stereo", + 8, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x7F\x80\xFF", 4, + 8, 2, 8000, 0, ENDIAN_LITTLE, "\x00\x00\x7F\x7F\x80\x80\xFF\xFF", 8 + }, + { + "stereo to mono", + 8, 2, 8000, 0, ENDIAN_LITTLE, "\x00\x01\x7F\x02\x80\x03\xFF\x04", 8, + 8, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x7F\x80\xFF", 4 + }, + { + "endian flip little->big", + 16, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x01\x00\xFF\x01\x00\x01\xFF", 8, + 16, 1, 8000, 0, ENDIAN_BIG, "\x01\x00\xFF\x00\x00\x01\xFF\x01", 8, + }, + { + "endian flip big->little", + 16, 1, 8000, 0, ENDIAN_BIG, "\x01\x00\xFF\x00\x00\x01\xFF\x01", 8, + 16, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x01\x00\xFF\x01\x00\x01\xFF", 8, + }, + { + "8-bit to 16-bit", + 8, 1, 8000, 0, ENDIAN_BIG, "\x00\x7F\x80\xFF", 4, + 16, 1, 8000, 0, ENDIAN_BIG, "\x00\x00\x7F\x00\x80\x00\xFF\x00", 8 + }, + { + "16-bit to 8-bit", + 16, 1, 8000, 0, ENDIAN_BIG, "\x00\x00\x7F\xFF\x80\x00\xFF\xFF", 8, + 8, 1, 8000, 0, ENDIAN_BIG, "\x00\x7F\x80\xFF", 4 + }, +#if HAVE_SAMPLERATE_H + /* Conversions that do change the sample rate */ + +#endif +}; +#define NCONVERSIONS (sizeof conversions / sizeof *conversions) + +static void test_resample(void) { + for(size_t n = 0; n < NCONVERSIONS; ++n) { + struct resampler rs[1]; + + resample_init(rs, + conversions[n].input_bits, + conversions[n].input_channels, + conversions[n].input_rate, + conversions[n].input_signed, + conversions[n].input_endian, + conversions[n].output_bits, + conversions[n].output_channels, + conversions[n].output_rate, + conversions[n].output_signed, + conversions[n].output_endian); + size_t output_bytes; + const uint8_t *output = convert(rs, + (const uint8_t *)conversions[n].input, + conversions[n].input_bytes, + &output_bytes); + if(output_bytes != conversions[n].output_bytes + || memcmp(output, conversions[n].output, output_bytes)) { + fprintf(stderr, "index %zu description %s mismatch\n", + n, conversions[n].description); + size_t k = 0; + while(k < conversions[n].output_bytes || k < output_bytes) { + size_t j = 0; + fprintf(stderr, "%8zu E:", k); + for(j = 0; j < 16; ++j) { + if(j + k < conversions[n].output_bytes) + fprintf(stderr, " %02x", conversions[n].output[j + k]); + } + fprintf(stderr, "\n G:"); + for(j = 0; j < 16; ++j) { + if(j + k < output_bytes) + fprintf(stderr, " %02x", output[j + k]); + } + fprintf(stderr, "\n"); + k += 16; + } + ++errors; + } + ++tests; + } +} + +TEST(resample); + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/