TESTS
tiny_resample.h
/**
* @file tiny_resample_test.h
* @author SHUAIWEN CUI (SHUAIWEN001@e.ntu.edu.sg)
* @brief tiny_resample | test | header
* @version 1.0
* @date 2025-04-29
* @copyright Copyright (c) 2025
*
*/
#pragma once
/* DEPENDENCIES */
#include "tiny_resample.h"
#ifdef __cplusplus
extern "C"
{
#endif
void tiny_resample_test(void);
#ifdef __cplusplus
}
#endif
tiny_resample.c
/**
* @file tiny_resample_test.c
* @author SHUAIWEN CUI (SHUAIWEN001@e.ntu.edu.sg)
* @brief tiny_resample | test | source
* @version 1.0
* @date 2025-04-29
* @copyright Copyright (c) 2025
*
*/
/* DEPENDENCIES */
#include "tiny_resample_test.h" // tiny_resample test header
#include <math.h> // for fabs()
void tiny_resample_test(void)
{
printf("========== TinyResample Test ==========\n\n");
// Original signal
const float input[] = {1, 2, 3, 4, 5, 6, 7, 8};
const int input_len = sizeof(input) / sizeof(input[0]);
printf("Original Signal (length=%d):\n", input_len);
printf(" Input: ");
for (int i = 0; i < input_len; i++) printf(" %.2f", input[i]);
printf("\n\n");
// ============================================================
// Test 1: Downsampling
// Pattern: copy `keep` samples, drop the next `skip` samples, repeat.
// With keep=1, skip=1 the effective stride is 2 (drop every second
// sample) -> from input[1..8] we should get [1, 3, 5, 7].
// ============================================================
printf("Test 1: Downsampling (keep=1, skip=1, effective stride=2)\n");
printf(" Description: Keep one sample then skip one, repeat\n");
printf(" Input: ");
for (int i = 0; i < input_len; i++) printf(" %.2f", input[i]);
printf(" (length=%d)\n", input_len);
float downsampled[8];
int down_len = 0;
tiny_downsample_skip_f32(input, input_len, downsampled, &down_len, 1, 1);
printf(" Output: ");
for (int i = 0; i < down_len; i++) printf(" %.2f", downsampled[i]);
printf(" (length=%d)\n", down_len);
printf(" Expected: input[0,2,4,6] -> [1.00, 3.00, 5.00, 7.00]\n\n");
// Optional second case to demonstrate keep > 1.
printf("Test 1b: Downsampling (keep=2, skip=1)\n");
printf(" Description: Keep two samples then skip one, repeat\n");
float down2[8];
int down2_len = 0;
tiny_downsample_skip_f32(input, input_len, down2, &down2_len, 2, 1);
printf(" Output: ");
for (int i = 0; i < down2_len; i++) printf(" %.2f", down2[i]);
printf(" (length=%d)\n", down2_len);
printf(" Expected: input[0,1,3,4,6,7] -> [1.00, 2.00, 4.00, 5.00, 7.00, 8.00]\n\n");
// ============================================================
// Test 2: Upsampling
// ============================================================
printf("Test 2: Upsampling (Zero-insertion)\n");
printf(" Description: Insert zeros between samples to increase length\n");
printf(" Input: ");
for (int i = 0; i < down_len; i++) printf(" %.2f", downsampled[i]);
printf(" (length=%d)\n", down_len);
float upsampled[16];
tiny_upsample_zero_f32(downsampled, down_len, upsampled, 16);
printf(" Output: ");
for (int i = 0; i < 16; i++) printf(" %.2f", upsampled[i]);
printf(" (length=16)\n");
printf(" Mapping: input[0,1,2,3] -> output[0,4,8,12] = [1.00, 3.00, 5.00, 7.00]\n");
printf(" (zeros inserted at positions 1,2,3,5,6,7,9,10,11,13,14,15)\n\n");
// ============================================================
// Test 3: Resampling
// ============================================================
printf("Test 3: Resampling (Linear Interpolation)\n");
printf(" Description: Resample from %d to 12 samples using linear interpolation\n", input_len);
printf(" Input: ");
for (int i = 0; i < input_len; i++) printf(" %.2f", input[i]);
printf(" (length=%d)\n", input_len);
float resampled[12];
tiny_resample_f32(input, input_len, resampled, 12);
printf(" Output: ");
for (int i = 0; i < 12; i++) printf(" %.2f", resampled[i]);
printf(" (length=12)\n");
printf(" Mapping: Linear interpolation between input samples\n");
printf(" output[0,2,4,6,8,10] = input[0,1,2,3,4,5] = [1.00, 2.00, 3.00, 4.00, 5.00, 6.00]\n");
printf(" output[1,3,5,7,9,11] = interpolated midpoints\n\n");
// ============================================================
// Test 4: Validation - Verify interpolation correctness
// ============================================================
printf("Test 4: Validation - Verify Linear Interpolation Correctness\n");
printf(" Purpose: Verify interpolation / edge clamping behavior\n");
printf(" if index < input_len-1: output = input[index]*(1-frac) + input[index+1]*frac\n");
printf(" else (tail): output = input[input_len-1] (clamped)\n\n");
float ratio = 12.0f / 8.0f;
int validation_errors = 0;
printf(" Sample verification (checking a few key points):\n");
for (int i = 0; i < 12; i++) {
float pos = i / ratio;
int index = (int)floorf(pos);
float frac = pos - index;
float expected;
if (index >= input_len - 1) {
expected = input[input_len - 1];
} else {
expected = input[index] * (1.0f - frac) + input[index + 1] * frac;
}
float diff = fabsf(resampled[i] - expected);
if (diff > 0.01f) {
validation_errors++;
}
// Only print a few key points to avoid clutter
if (i == 0 || i == 1 || i == 2 || i == 6 || i == 11) {
if (index >= input_len - 1) {
printf(" output[%2d]: pos=%.3f, index=%d (tail clamp) -> %.2f (expected: %.2f) %s\n",
i, pos, index, resampled[i], expected,
(diff < 0.01f) ? "[OK]" : "[X]");
} else {
printf(" output[%2d]: pos=%.3f, index=%d, frac=%.3f -> %.2f (expected: %.2f) %s\n",
i, pos, index, frac, resampled[i], expected,
(diff < 0.01f) ? "[OK]" : "[X]");
}
}
}
if (validation_errors == 0) {
printf(" [PASS] All interpolated values are correct.\n");
} else {
printf(" [FAIL] Found %d interpolation errors\n", validation_errors);
}
printf("\n========================================\n");
}
Test Output
========== TinyResample Test ==========
Original Signal (length=8):
Input: 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00
Test 1: Downsampling (keep=1, skip=1, effective stride=2)
Description: Keep one sample then skip one, repeat
Input: 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 (length=8)
Output: 1.00 3.00 5.00 7.00 (length=4)
Expected: input[0,2,4,6] -> [1.00, 3.00, 5.00, 7.00]
Test 1b: Downsampling (keep=2, skip=1)
Description: Keep two samples then skip one, repeat
Output: 1.00 2.00 4.00 5.00 7.00 8.00 (length=6)
Expected: input[0,1,3,4,6,7] -> [1.00, 2.00, 4.00, 5.00, 7.00, 8.00]
Test 2: Upsampling (Zero-insertion)
Description: Insert zeros between samples to increase length
Input: 1.00 3.00 5.00 7.00 (length=4)
Output: 1.00 0.00 0.00 0.00 3.00 0.00 0.00 0.00 5.00 0.00 0.00 0.00 7.00 0.00 0.00 0.00 (length=16)
Mapping: input[0,1,2,3] -> output[0,4,8,12] = [1.00, 3.00, 5.00, 7.00]
(zeros inserted at positions 1,2,3,5,6,7,9,10,11,13,14,15)
Test 3: Resampling (Linear Interpolation)
Description: Resample from 8 to 12 samples using linear interpolation
Input: 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 (length=8)
Output: 1.00 1.67 2.33 3.00 3.67 4.33 5.00 5.67 6.33 7.00 7.67 8.00 (length=12)
Mapping: Linear interpolation between input samples
output[0,2,4,6,8,10] = input[0,1,2,3,4,5] = [1.00, 2.00, 3.00, 4.00, 5.00, 6.00]
output[1,3,5,7,9,11] = interpolated midpoints
Test 4: Validation - Verify Linear Interpolation Correctness
Purpose: Verify interpolation / edge clamping behavior
if index < input_len-1: output = input[index]*(1-frac) + input[index+1]*frac
else (tail): output = input[input_len-1] (clamped)
Sample verification (checking a few key points):
output[ 0]: pos=0.000, index=0, frac=0.000 -> 1.00 (expected: 1.00) [OK]
output[ 1]: pos=0.667, index=0, frac=0.667 -> 1.67 (expected: 1.67) [OK]
output[ 2]: pos=1.333, index=1, frac=0.333 -> 2.33 (expected: 2.33) [OK]
output[ 6]: pos=4.000, index=4, frac=0.000 -> 5.00 (expected: 5.00) [OK]
output[11]: pos=7.333, index=7 (tail clamp) -> 8.00 (expected: 8.00) [OK]
[PASS] All interpolated values are correct.
========================================