diff --git a/include/wavetable.h b/include/wavetable.h index cef31f7..4407fe0 100644 --- a/include/wavetable.h +++ b/include/wavetable.h @@ -1,5 +1,6 @@ #pragma once #include "stddef.h" +#include "vec.h" typedef enum { WAVEFORM_SINE, @@ -18,3 +19,13 @@ typedef struct { Wavetable *wavetable_create(Waveform type, size_t length); void wavetable_set_custom(Wavetable *wt, float *data, size_t length); void wavetable_destroy(Wavetable *wt); + +typedef struct { + Vec *vec; +} WtVec; + +WtVec *WtVec_create(void); +void WtVec_push(WtVec *wv, Wavetable *wt); +Wavetable *WtVec_get(const WtVec *wv, size_t index); +size_t WtVec_size(const WtVec *wv); +void WtVec_destroy(WtVec *wv); diff --git a/src/wavetable.c b/src/wavetable.c index b410cbe..f9e83f6 100644 --- a/src/wavetable.c +++ b/src/wavetable.c @@ -55,3 +55,22 @@ void wavetable_destroy(Wavetable *wt) { free(wt->data); free(wt); } + +WtVec *WtVec_create(void) { + WtVec *ov = malloc(sizeof(WtVec)); + ov->vec = vec_create(sizeof(Wavetable *), (ElemDestroyFunc)wavetable_destroy); + return ov; +} + +void WtVec_push(WtVec *ov, Wavetable *osc) { vec_push_back(ov->vec, &osc); } + +Wavetable *WtVec_get(const WtVec *ov, size_t index) { + return ((Wavetable **)(ov->vec->data))[index]; +} + +size_t WtVec_size(const WtVec *ov) { return ov->vec->size; } + +void WtVec_destroy(WtVec *ov) { + vec_destroy(ov->vec); + free(ov); +} diff --git a/tests/test_wavetable.c b/tests/test_wavetable.c index 12ebac7..173645b 100644 --- a/tests/test_wavetable.c +++ b/tests/test_wavetable.c @@ -73,3 +73,45 @@ Test(wavetable, triangle_generation) { // // wavetable_destroy(wt); // } + +Test(wtvec, push_get_and_destroy) { + WtVec *wv = WtVec_create(); + cr_assert_not_null(wv, "WtVec_create returned NULL"); + cr_assert_eq(WtVec_size(wv), 0, "Initial WtVec size should be 0"); + + size_t length1 = 100; + Wavetable *wt1 = wavetable_create(WAVEFORM_SINE, length1); + cr_assert_not_null(wt1, "wavetable_create returned NULL for sine"); + WtVec_push(wv, wt1); + cr_assert_eq(WtVec_size(wv), 1, "After pushing sine wavetable, size should be 1"); + + size_t length2 = 50; + Wavetable *wt2 = wavetable_create(WAVEFORM_SAW, length2); + cr_assert_not_null(wt2, "wavetable_create returned NULL for saw"); + WtVec_push(wv, wt2); + cr_assert_eq(WtVec_size(wv), 2, "After pushing saw wavetable, size should be 2"); + + Wavetable *retrieved1 = WtVec_get(wv, 0); + cr_assert_not_null(retrieved1, "Retrieved wavetable 1 is NULL"); + cr_assert_eq(retrieved1->type, WAVEFORM_SINE, "Retrieved wavetable 1 type mismatch"); + cr_assert_eq(retrieved1->length, length1, "Retrieved wavetable 1 length mismatch"); + + for (size_t i = 0; i < length1; i++) { + float expected = (float)sin(2.0 * M_PI * i / length1); + cr_assert_float_eq(retrieved1->data[i], expected, 0.0001, + "Sine wavetable sample at index %zu incorrect", i); + } + + Wavetable *retrieved2 = WtVec_get(wv, 1); + cr_assert_not_null(retrieved2, "Retrieved wavetable 2 is NULL"); + cr_assert_eq(retrieved2->type, WAVEFORM_SAW, "Retrieved wavetable 2 type mismatch"); + cr_assert_eq(retrieved2->length, length2, "Retrieved wavetable 2 length mismatch"); + + for (size_t i = 0; i < length2; i++) { + float expected = 2.0f * i / length2 - 1.0f; + cr_assert_float_eq(retrieved2->data[i], expected, 0.0001, + "Saw wavetable sample at index %zu incorrect", i); + } + + WtVec_destroy(wv); +}