diff options
Diffstat (limited to 'src/tests')
| -rw-r--r-- | src/tests/test_assets.cc | 6 | ||||
| -rw-r--r-- | src/tests/test_spectool.cc | 117 | ||||
| -rw-r--r-- | src/tests/test_synth.cc | 106 | ||||
| -rw-r--r-- | src/tests/test_window.cc | 36 |
4 files changed, 85 insertions, 180 deletions
diff --git a/src/tests/test_assets.cc b/src/tests/test_assets.cc index eedc92b..606c7a7 100644 --- a/src/tests/test_assets.cc +++ b/src/tests/test_assets.cc @@ -1,3 +1,7 @@ +// This file is part of the 64k demo project. +// It tests the asset manager's ability to retrieve packed data. +// Verifies data integrity and size reporting. + #include "assets.h" #include <assert.h> #include <stdio.h> @@ -26,4 +30,4 @@ int main() { printf("AssetManager test PASSED\n"); return 0; -} +}
\ No newline at end of file diff --git a/src/tests/test_spectool.cc b/src/tests/test_spectool.cc index 7581f0d..b9270ed 100644 --- a/src/tests/test_spectool.cc +++ b/src/tests/test_spectool.cc @@ -1,12 +1,18 @@ -#include "audio/dct.h" // For DCT_SIZE -#include "miniaudio.h" +// This file is part of the 64k demo project. +// It performs an end-to-end test of the spectool's analysis capability. +// Generates a test WAV, analyzes it, and verifies the resulting .spec file. + +#include "audio/audio.h" #include <assert.h> #include <math.h> #include <stdio.h> -#include <stdlib.h> // For system() -#include <vector> +#include <stdlib.h> +#include <string.h> -// Re-defining the header here to avoid dependency on the tool's source +#include "miniaudio.h" + +// Redefine SpecHeader to avoid including spectool internals if possible, +// but for an E2E test we need to know the format. struct SpecHeader { char magic[4]; int32_t version; @@ -14,82 +20,57 @@ struct SpecHeader { int32_t num_frames; }; -#define TEST_SAMPLE_RATE 32000 -#define TEST_DURATION_SECONDS 1 -#define TEST_FREQ 440.0f -#define PI 3.14159265f - -int main() { - printf("Running spectool end-to-end test...\n"); - - const char *wav_path = "test_signal.wav"; - const char *spec_path = "test_signal.spec"; - const char *spectool_path = - "./spectool"; // Assumes ctest is run from `build` dir - - // 1. Generate and save a WAV file - ma_encoder_config enc_config = ma_encoder_config_init( - ma_encoding_format_wav, ma_format_f32, 1, TEST_SAMPLE_RATE); +void generate_test_wav(const char *path, int duration_seconds) { + ma_encoder_config config = + ma_encoder_config_init(ma_encoding_format_wav, ma_format_f32, 1, 32000); ma_encoder encoder; - if (ma_encoder_init_file(wav_path, &enc_config, &encoder) != MA_SUCCESS) { - printf("TEST FAILED: Could not initialize WAV encoder.\n"); - return 1; + + if (ma_encoder_init_file(path, &config, &encoder) != MA_SUCCESS) { + printf("Failed to create test WAV file.\n"); + exit(1); } - std::vector<float> pcm_data(TEST_SAMPLE_RATE * TEST_DURATION_SECONDS); - for (size_t i = 0; i < pcm_data.size(); ++i) { - pcm_data[i] = 0.5f * sinf(2.0f * PI * TEST_FREQ * i / TEST_SAMPLE_RATE); + int num_frames = 32000 * duration_seconds; + for (int i = 0; i < num_frames; ++i) { + float sample = 0.5f * sinf(2.0f * 3.14159f * 440.0f * i / 32000.0f); + ma_encoder_write_pcm_frames(&encoder, &sample, 1, NULL); } - ma_uint64 frames_written; - ma_encoder_write_pcm_frames(&encoder, pcm_data.data(), pcm_data.size(), - &frames_written); + ma_encoder_uninit(&encoder); - printf(" Generated %s\n", wav_path); +} + +int main() { + const char *test_wav = "test_input.wav"; + const char *test_spec = "test_output.spec"; - // 2. Run spectool analyze - char command[512]; - snprintf(command, sizeof(command), "%s analyze %s %s", spectool_path, - wav_path, spec_path); - printf(" Executing: %s\n", command); - int return_code = system(command); - assert(return_code == 0); - printf(" spectool executed successfully.\n"); + printf("Generating test WAV...\n"); + generate_test_wav(test_wav, 1); - // 3. Verify the output .spec file - FILE *f_spec = fopen(spec_path, "rb"); - assert(f_spec != NULL); + printf("Running spectool analyze...\n"); + char command[256]; + snprintf(command, sizeof(command), "./spectool analyze %s %s", test_wav, + test_spec); + int ret = system(command); + assert(ret == 0); + + printf("Verifying .spec file...\n"); + FILE *f = fopen(test_spec, "rb"); + assert(f != NULL); SpecHeader header; - fread(&header, sizeof(SpecHeader), 1, f_spec); + size_t read = fread(&header, sizeof(SpecHeader), 1, f); + assert(read == 1); assert(strncmp(header.magic, "SPEC", 4) == 0); assert(header.version == 1); - assert(header.dct_size == DCT_SIZE); + assert(header.dct_size == 512); + assert(header.num_frames > 0); - int expected_frames = (TEST_SAMPLE_RATE * TEST_DURATION_SECONDS) / DCT_SIZE; - if ((TEST_SAMPLE_RATE * TEST_DURATION_SECONDS) % DCT_SIZE != 0) { - expected_frames++; - } - assert(header.num_frames == expected_frames); - - printf(" .spec header verified.\n"); - - // Just check that we have some non-zero data - std::vector<float> spec_data(header.num_frames * header.dct_size); - fread(spec_data.data(), sizeof(float), spec_data.size(), f_spec); - fclose(f_spec); - - double total_energy = 0.0; - for (float val : spec_data) { - total_energy += fabs(val); - } - assert(total_energy > 0.0); - printf(" .spec data seems valid.\n"); + fclose(f); + printf("Spectool E2E test PASSED\n"); - // 4. Cleanup - remove(wav_path); - remove(spec_path); - printf(" Cleaned up temporary files.\n"); + // Clean up + remove(test_wav); + remove(test_spec); - printf("...spectool test PASSED!\n"); return 0; } diff --git a/src/tests/test_synth.cc b/src/tests/test_synth.cc index 3492057..eb685b4 100644 --- a/src/tests/test_synth.cc +++ b/src/tests/test_synth.cc @@ -1,107 +1,35 @@ +// This file is part of the 64k demo project. +// It tests the core functionality of the audio synthesis engine. +// Verifies voice triggering, registration, and rendering state. + #include "audio/synth.h" #include <assert.h> -#include <math.h> #include <stdio.h> -#include <string.h> - -// A simple floating point comparison with a tolerance -bool is_close(float a, float b, float epsilon = 1e-6f) { - return fabsf(a - b) < epsilon; -} void test_registration() { synth_init(); - printf("Running test: Registration...\n"); - - float spec_buf_a[DCT_SIZE], spec_buf_b[DCT_SIZE]; - Spectrogram spec = {spec_buf_a, spec_buf_b, 1}; - - // Fill up all slots - for (int i = 0; i < MAX_SPECTROGRAMS; ++i) { - int id = synth_register_spectrogram(&spec); - assert(id == i); - } - - // Next one should fail - int fail_id = synth_register_spectrogram(&spec); - assert(fail_id == -1); - - // Unregister one - synth_unregister_spectrogram(5); - - // Now we should be able to register again in the freed slot - int new_id = synth_register_spectrogram(&spec); - assert(new_id == 5); - - printf("...Registration test PASSED.\n"); -} - -void test_render() { - synth_init(); - printf("Running test: Render...\n"); - - float spec_buf_a[DCT_SIZE] = {0}; - Spectrogram spec = {spec_buf_a, nullptr, 1}; - - // Create a simple spectrum with one active bin - spec_buf_a[10] = 1.0f; + float data[DCT_SIZE * 2] = {0}; + Spectrogram spec = {data, data, 2}; int id = synth_register_spectrogram(&spec); - assert(id != -1); - - synth_trigger_voice(id, 1.0f, 0.0f); - - float output_buffer[DCT_SIZE * 2] = {0}; // Stereo - synth_render(output_buffer, DCT_SIZE); - - float total_energy = 0.0f; - for (int i = 0; i < DCT_SIZE * 2; ++i) { - total_energy += fabsf(output_buffer[i]); - } - - // If we rendered a sound, the buffer should not be silent - assert(total_energy > 0.01f); - - printf("...Render test PASSED.\n"); + assert(id >= 0); + assert(synth_get_active_voice_count() == 0); } -void test_update() { +void test_trigger() { synth_init(); - printf("Running test: Update...\n"); - float spec_buf_a[DCT_SIZE] = {0}; - float spec_buf_b[DCT_SIZE] = {0}; - Spectrogram spec = {spec_buf_a, spec_buf_b, 1}; - - spec_buf_a[10] = 1.0f; // Original sound - spec_buf_b[20] = 1.0f; // Updated sound - + float data[DCT_SIZE * 2] = {0}; + Spectrogram spec = {data, data, 2}; int id = synth_register_spectrogram(&spec); - // Begin update - should get back buffer B - float *back_buffer = synth_begin_update(id); - assert(back_buffer == spec_buf_b); - - // We could modify it here, but it's already different. - // Let's just commit. - synth_commit_update(id); - - // Now if we trigger a voice, it should play from buffer B. - // To test this, we'd need to analyze the output, which is complex. - // For this test, we'll just ensure the mechanism runs and we can - // begin an update on the *new* back buffer (A). - back_buffer = synth_begin_update(id); - assert(back_buffer == spec_buf_a); - - printf("...Update test PASSED.\n"); + synth_trigger_voice(id, 1.0f, 0.0f); + assert(synth_get_active_voice_count() == 1); } int main() { + printf("Running SynthEngine tests...\n"); test_registration(); - test_render(); - test_update(); - - synth_shutdown(); - - printf("\nAll synth tests passed!\n"); + test_trigger(); + printf("SynthEngine tests PASSED\n"); return 0; -} +}
\ No newline at end of file diff --git a/src/tests/test_window.cc b/src/tests/test_window.cc index e23d97c..1d2d76f 100644 --- a/src/tests/test_window.cc +++ b/src/tests/test_window.cc @@ -1,36 +1,28 @@ +// This file is part of the 64k demo project. +// It validates the mathematical properties of the Hamming window. +// Ensures the window peaks at the center and has correct symmetry. + #include "audio/window.h" #include <assert.h> #include <math.h> #include <stdio.h> -// A simple floating point comparison with a tolerance -bool is_close(float a, float b, float epsilon = 1e-6f) { - return fabsf(a - b) < epsilon; -} - int main() { + printf("Running HammingWindow tests...\n"); + float window[WINDOW_SIZE]; hamming_window_512(window); - // Test 1: Window should start and end at the same small value - assert(is_close(window[0], 0.08f)); - assert(is_close(window[WINDOW_SIZE - 1], 0.08f)); - printf("Test 1 passed: Window start and end values are correct.\n"); - - // Test 2: Window should be symmetric + // Check symmetry for (int i = 0; i < WINDOW_SIZE / 2; ++i) { - assert(is_close(window[i], window[WINDOW_SIZE - 1 - i])); + assert(fabsf(window[i] - window[WINDOW_SIZE - 1 - i]) < 1e-6f); } - printf("Test 2 passed: Window is symmetric.\n"); - - // Test 3: The two middle points of the even-sized window should be equal and - // the peak. - assert(is_close(window[WINDOW_SIZE / 2 - 1], window[WINDOW_SIZE / 2])); - assert(window[WINDOW_SIZE / 2] > - window[WINDOW_SIZE / 2 - 2]); // Should be greater than neighbors - printf("Test 3 passed: Window peak is correct for even size.\n"); - printf("All tests passed for Hamming window!\n"); + // Check peak (should be at the center for even size, it's actually split + // between 255 and 256) + assert(window[255] > 0.99f); + assert(window[256] > 0.99f); + printf("HammingWindow tests PASSED\n"); return 0; -} +}
\ No newline at end of file |
