summaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/test_spectool.cc95
-rw-r--r--src/tests/test_spectool.cpp91
-rw-r--r--src/tests/test_synth.cc107
-rw-r--r--src/tests/test_synth.cpp107
-rw-r--r--src/tests/test_window.cc36
-rw-r--r--src/tests/test_window.cpp34
6 files changed, 238 insertions, 232 deletions
diff --git a/src/tests/test_spectool.cc b/src/tests/test_spectool.cc
new file mode 100644
index 0000000..7581f0d
--- /dev/null
+++ b/src/tests/test_spectool.cc
@@ -0,0 +1,95 @@
+#include "audio/dct.h" // For DCT_SIZE
+#include "miniaudio.h"
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h> // For system()
+#include <vector>
+
+// Re-defining the header here to avoid dependency on the tool's source
+struct SpecHeader {
+ char magic[4];
+ int32_t version;
+ int32_t dct_size;
+ 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);
+ 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;
+ }
+
+ 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);
+ }
+ 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);
+
+ // 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");
+
+ // 3. Verify the output .spec file
+ FILE *f_spec = fopen(spec_path, "rb");
+ assert(f_spec != NULL);
+
+ SpecHeader header;
+ fread(&header, sizeof(SpecHeader), 1, f_spec);
+ assert(strncmp(header.magic, "SPEC", 4) == 0);
+ assert(header.version == 1);
+ assert(header.dct_size == DCT_SIZE);
+
+ 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");
+
+ // 4. Cleanup
+ remove(wav_path);
+ remove(spec_path);
+ printf(" Cleaned up temporary files.\n");
+
+ printf("...spectool test PASSED!\n");
+ return 0;
+}
diff --git a/src/tests/test_spectool.cpp b/src/tests/test_spectool.cpp
deleted file mode 100644
index ae64cc3..0000000
--- a/src/tests/test_spectool.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h> // For system()
-#include <vector>
-#include <math.h>
-#include "miniaudio.h"
-#include "audio/dct.h" // For DCT_SIZE
-
-// Re-defining the header here to avoid dependency on the tool's source
-struct SpecHeader {
- char magic[4];
- int32_t version;
- int32_t dct_size;
- 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);
- 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;
- }
-
- 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);
- }
- 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);
-
- // 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");
-
- // 3. Verify the output .spec file
- FILE* f_spec = fopen(spec_path, "rb");
- assert(f_spec != NULL);
-
- SpecHeader header;
- fread(&header, sizeof(SpecHeader), 1, f_spec);
- assert(strncmp(header.magic, "SPEC", 4) == 0);
- assert(header.version == 1);
- assert(header.dct_size == DCT_SIZE);
-
- 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");
-
- // 4. Cleanup
- remove(wav_path);
- remove(spec_path);
- printf(" Cleaned up temporary files.\n");
-
- printf("...spectool test PASSED!\n");
- return 0;
-}
diff --git a/src/tests/test_synth.cc b/src/tests/test_synth.cc
new file mode 100644
index 0000000..3492057
--- /dev/null
+++ b/src/tests/test_synth.cc
@@ -0,0 +1,107 @@
+#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;
+
+ 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");
+}
+
+void test_update() {
+ 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
+
+ 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");
+}
+
+int main() {
+ test_registration();
+ test_render();
+ test_update();
+
+ synth_shutdown();
+
+ printf("\nAll synth tests passed!\n");
+ return 0;
+}
diff --git a/src/tests/test_synth.cpp b/src/tests/test_synth.cpp
deleted file mode 100644
index 04b0373..0000000
--- a/src/tests/test_synth.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "audio/synth.h"
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <math.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;
-
- 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");
-}
-
-void test_update() {
- 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
-
- 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");
-}
-
-int main() {
- test_registration();
- test_render();
- test_update();
-
- synth_shutdown();
-
- printf("\nAll synth tests passed!\n");
- return 0;
-}
diff --git a/src/tests/test_window.cc b/src/tests/test_window.cc
new file mode 100644
index 0000000..e23d97c
--- /dev/null
+++ b/src/tests/test_window.cc
@@ -0,0 +1,36 @@
+#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() {
+ 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
+ for (int i = 0; i < WINDOW_SIZE / 2; ++i) {
+ assert(is_close(window[i], window[WINDOW_SIZE - 1 - i]));
+ }
+ 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");
+
+ return 0;
+}
diff --git a/src/tests/test_window.cpp b/src/tests/test_window.cpp
deleted file mode 100644
index 1667dab..0000000
--- a/src/tests/test_window.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "audio/window.h"
-#include <stdio.h>
-#include <math.h>
-#include <assert.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() {
- 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
- for (int i = 0; i < WINDOW_SIZE / 2; ++i) {
- assert(is_close(window[i], window[WINDOW_SIZE - 1 - i]));
- }
- 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");
-
- return 0;
-}