From 3f4cb663f171ecb5c6fc3262fb6156efb3f1ddd2 Mon Sep 17 00:00:00 2001 From: Christian Hoene Date: Fri, 23 Jan 2026 01:09:48 +0100 Subject: [PATCH 1/2] added support for General FIR-E --- CMakeLists.txt | 3 +++ src/hdf/btree.c | 63 ++++++++++++++++++++++++++++++------------- src/hdf/dataobject.c | 30 ++++++++++----------- src/hdf/reader.h | 8 +++--- tests/testfile.sofa | Bin 0 -> 37848 bytes 5 files changed, 65 insertions(+), 39 deletions(-) create mode 100644 tests/testfile.sofa diff --git a/CMakeLists.txt b/CMakeLists.txt index d4169bb..4e79cfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,9 @@ if(BUILD_TESTS) enable_testing() + + add_test(NAME GeneralFIR-E COMMAND src/mysofa2json -o tmp.json + ${PROJECT_SOURCE_DIR}/tests/testfile.sofa) add_test(NAME Mesh2HRTF COMMAND src/mysofa2json -c -o tmp.json ${PROJECT_SOURCE_DIR}/tests/Mesh2HRTF.sofa) add_test(NAME latTestAziBeRTA_Resamp1_Fran COMMAND src/mysofa2json -c -o tmp.json diff --git a/src/hdf/btree.c b/src/hdf/btree.c index 7bb2236..fb37dbc 100644 --- a/src/hdf/btree.c +++ b/src/hdf/btree.c @@ -7,9 +7,9 @@ #include "reader.h" #include #include +#include #include #include -#include /* * @@ -212,16 +212,16 @@ void btreeFree(struct BTREE *btree) { free(btree->records); } int treeRead(struct READER *reader, struct DATAOBJECT *data) { - int i, j, err, olen, elements, size, x, y, z, b, e, dy, dz, sx, sy, sz, dzy, - szy; + int i, j, err, olen, elements, size, x, y, z, w, b, e, dy, dz, sx, sy, sz, dw, + sw, k; char *input, *output; uint8_t node_type, node_level; uint16_t entries_used; uint32_t size_of_chunk; uint32_t filter_mask; - uint64_t address_of_left_sibling, address_of_right_sibling, start[4], - child_pointer, key, store; + uint64_t address_of_left_sibling, address_of_right_sibling, + start[HDF_MAX_DIMENSIONALITY], child_pointer, key, store; char buf[5]; @@ -230,9 +230,9 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { UNUSED(address_of_left_sibling); UNUSED(key); - if (data->ds.dimensionality > 3) { - mylog("TREE dimensions > 3"); // LCOV_EXCL_LINE - return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE + if (data->ds.dimensionality > HDF_MAX_DIMENSIONALITY) { + mylog("TREE dimensions > %d\n", HDF_MAX_DIMENSIONALITY); // LCOV_EXCL_LINE + return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } /* read signature */ @@ -258,16 +258,16 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { elements *= data->datalayout_chunk[j]; dy = data->datalayout_chunk[1]; dz = data->datalayout_chunk[2]; + dw = data->datalayout_chunk[3]; sx = data->ds.dimension_size[0]; sy = data->ds.dimension_size[1]; sz = data->ds.dimension_size[2]; - dzy = dz * dy; - szy = sz * sy; + sw = data->ds.dimension_size[3]; size = data->datalayout_chunk[data->ds.dimensionality]; mylog("elements %d size %d\n", elements, size); - if (elements <= 0 || size <= 0 || elements > INT_MAX/size) + if (elements <= 0 || size <= 0 || elements > INT_MAX / size) return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE if (!(output = malloc(elements * size))) { return MYSOFA_NO_MEMORY; // LCOV_EXCL_LINE @@ -338,12 +338,14 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { } } break; + case 2: for (i = 0; i < olen; i++) { b = i / elements; - x = i % elements; - y = x % dy + start[1]; - x = x / dy + start[0]; + k = i % elements; + y = k % dy + start[1]; + k = k / dy; + x = k + start[0]; if (y < sy && x < sx) { j = ((x * sy + y) * size) + b; if (j >= 0 && j < data->data_len) { @@ -352,15 +354,38 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { } } break; + case 3: for (i = 0; i < olen; i++) { b = i / elements; - x = i % elements; - z = x % dz + start[2]; - y = (x / dz) % dy + start[1]; - x = (x / dzy) + start[0]; + k = i % elements; + z = k % dz + start[2]; + k = k / dz; + y = k % dy + start[1]; + k = k / dy; + x = k + start[0]; if (z < sz && y < sy && x < sx) { - j = (x * szy + y * sz + z) * size + b; + j = ((x * sy + y) * sz + z) * size + b; + if (j >= 0 && j < data->data_len) { + ((char *)data->data)[j] = output[i]; + } + } + } + break; + + case 4: + for (i = 0; i < olen; i++) { + b = i / elements; + k = i % elements; + w = k % dw + start[3]; + k = k / dw; + z = k % dz + start[2]; + k = k / dz; + y = k % dy + start[1]; + k = k / dy; + x = k + start[0]; + if (z < sz && y < sy && x < sx && w < sw) { + j = (((x * sy + y) * sz + z) * sw + w) * size + b; if (j >= 0 && j < data->data_len) { ((char *)data->data)[j] = output[i]; } diff --git a/src/hdf/dataobject.c b/src/hdf/dataobject.c index ec6656b..df2d689 100644 --- a/src/hdf/dataobject.c +++ b/src/hdf/dataobject.c @@ -129,9 +129,10 @@ static int readOHDRHeaderMessageDataspace(struct READER *reader, int version = mysofa_getc(reader); ds->dimensionality = (uint8_t)mysofa_getc(reader); - if (ds->dimensionality > 4) { - mylog("dimensionality must be lower than 5\n"); // LCOV_EXCL_LINE - return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE + if (ds->dimensionality > HDF_MAX_DIMENSIONALITY) { + mylog("dimensionality must not be larger than %d\n", + HDF_MAX_DIMENSIONALITY); // LCOV_EXCL_LINE + return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } ds->flags = (uint8_t)mysofa_getc(reader); @@ -466,7 +467,7 @@ static int readOHDRHeaderMessageDataLayout(struct READER *reader, int i, err; uint64_t size; - uint8_t dimensionality, layout_class; + uint8_t layout_class; uint32_t dataset_element_size; uint64_t data_address, store, data_size; @@ -520,28 +521,25 @@ static int readOHDRHeaderMessageDataLayout(struct READER *reader, break; case 2: - dimensionality = (uint8_t)mysofa_getc(reader); - mylog("dimensionality %d\n", dimensionality); - - if (dimensionality < 1 || dimensionality > DATAOBJECT_MAX_DIMENSIONALITY) { - mylog("data layout 2: invalid dimensionality %d %lu %lu\n", - dimensionality, sizeof(data->datalayout_chunk), - sizeof(data->datalayout_chunk[0])); + i = mysofa_getc(reader); // chunk dimensionality is one greater than dataset + if (i != data->ds.dimensionality + 1) { + mylog("data layout 2: invalid dimensionality %d %lu %lu vs. %d\n", i, + sizeof(data->datalayout_chunk), sizeof(data->datalayout_chunk[0]), + data->ds.dimensionality); return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } data_address = readValue(reader, reader->superblock.size_of_offsets); mylog(" CHUNK %" PRIX64 "\n", data_address); - for (i = 0; i < dimensionality; i++) { + for (i = 0; i <= data->ds.dimensionality; i++) { data->datalayout_chunk[i] = readValue(reader, 4); - mylog(" %d\n", data->datalayout_chunk[i]); + mylog(" %d:%d\n", i, data->datalayout_chunk[i]); } /* TODO last entry? error in spec: ?*/ - - size = data->datalayout_chunk[dimensionality - 1]; + size = data->datalayout_chunk[data->ds.dimensionality]; for (i = 0; i < data->ds.dimensionality; i++) size *= data->ds.dimension_size[i]; - if (validAddress(reader, data_address) && dimensionality <= 4) { + if (validAddress(reader, data_address)) { store = mysofa_tell(reader); if (mysofa_seek(reader, data_address, SEEK_SET) < 0) return errno; // LCOV_EXCL_LINE diff --git a/src/hdf/reader.h b/src/hdf/reader.h index 6838995..76f7092 100644 --- a/src/hdf/reader.h +++ b/src/hdf/reader.h @@ -13,6 +13,8 @@ #define UNUSED(x) (void)(x) +#define HDF_MAX_DIMENSIONALITY 4 + struct READER; struct DIR; struct DATAOBJECT; @@ -84,7 +86,7 @@ struct ATTRIBUTEINFO { }; struct DATASPACE { - uint64_t dimension_size[4], dimension_max_size[4]; + uint64_t dimension_size[HDF_MAX_DIMENSIONALITY], dimension_max_size[HDF_MAX_DIMENSIONALITY]; uint8_t dimensionality, flags, type; }; @@ -107,8 +109,6 @@ struct DATATYPE { uint32_t list; /* size of a list in bytes */ }; -#define DATAOBJECT_MAX_DIMENSIONALITY 5 - struct DATAOBJECT { char *name; @@ -126,7 +126,7 @@ struct DATAOBJECT { struct BTREE attributes_btree; struct FRACTALHEAP attributes_heap; - int datalayout_chunk[DATAOBJECT_MAX_DIMENSIONALITY]; + int datalayout_chunk[HDF_MAX_DIMENSIONALITY + 1]; struct MYSOFA_ATTRIBUTE *attributes; struct DIR *directory; diff --git a/tests/testfile.sofa b/tests/testfile.sofa new file mode 100644 index 0000000000000000000000000000000000000000..50c5d0a17bf116d1f260e16d7dfab81ecbe3ccd0 GIT binary patch literal 37848 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 literal 0 HcmV?d00001 From a1c0440e21104e4dc60b564a1a5f05accfecdbb3 Mon Sep 17 00:00:00 2001 From: Christian Hoene Date: Sat, 24 Jan 2026 13:37:13 +0100 Subject: [PATCH 2/2] optimized code of btree loop --- src/hdf/btree.c | 96 ++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 69 deletions(-) diff --git a/src/hdf/btree.c b/src/hdf/btree.c index fb37dbc..674017a 100644 --- a/src/hdf/btree.c +++ b/src/hdf/btree.c @@ -212,8 +212,8 @@ void btreeFree(struct BTREE *btree) { free(btree->records); } int treeRead(struct READER *reader, struct DATAOBJECT *data) { - int i, j, err, olen, elements, size, x, y, z, w, b, e, dy, dz, sx, sy, sz, dw, - sw, k; + int d, p, b = 0, c[HDF_MAX_DIMENSIONALITY]; + int i, j, err, olen, elements, size, e; char *input, *output; uint8_t node_type, node_level; @@ -256,13 +256,6 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { elements = 1; for (j = 0; j < data->ds.dimensionality; j++) elements *= data->datalayout_chunk[j]; - dy = data->datalayout_chunk[1]; - dz = data->datalayout_chunk[2]; - dw = data->datalayout_chunk[3]; - sx = data->ds.dimension_size[0]; - sy = data->ds.dimension_size[1]; - sz = data->ds.dimension_size[2]; - sw = data->ds.dimension_size[3]; size = data->datalayout_chunk[data->ds.dimensionality]; mylog("elements %d size %d\n", elements, size); @@ -324,77 +317,42 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } - switch (data->ds.dimensionality) { - case 1: - for (i = 0; i < olen; i++) { - b = i / elements; - x = i % elements + start[0]; - if (x < sx) { + for (d = 0; d < data->ds.dimensionality; d++) { + c[d] = 0; + } - j = x * size + b; - if (j >= 0 && j < data->data_len) { - ((char *)data->data)[j] = output[i]; - } - } - } - break; + for (i = 0; i < olen; i++) { - case 2: - for (i = 0; i < olen; i++) { - b = i / elements; - k = i % elements; - y = k % dy + start[1]; - k = k / dy; - x = k + start[0]; - if (y < sy && x < sx) { - j = ((x * sy + y) * size) + b; - if (j >= 0 && j < data->data_len) { - ((char *)data->data)[j] = output[i]; - } + // calculate and check destination pointer + p = 0; + for (d = 0; d < data->ds.dimensionality; d++) { + if (c[d] + start[d] >= data->ds.dimension_size[d]) { + p = -1; + break; } + p = p * data->ds.dimension_size[d] + c[d] + start[d]; } - break; - case 3: - for (i = 0; i < olen; i++) { - b = i / elements; - k = i % elements; - z = k % dz + start[2]; - k = k / dz; - y = k % dy + start[1]; - k = k / dy; - x = k + start[0]; - if (z < sz && y < sy && x < sx) { - j = ((x * sy + y) * sz + z) * size + b; - if (j >= 0 && j < data->data_len) { - ((char *)data->data)[j] = output[i]; - } + // copy data if within bounds + if (p >= 0) { + p = p * size + b; + if (p < data->data_len) { + ((char *)data->data)[p] = output[i]; } } - break; - case 4: - for (i = 0; i < olen; i++) { - b = i / elements; - k = i % elements; - w = k % dw + start[3]; - k = k / dw; - z = k % dz + start[2]; - k = k / dz; - y = k % dy + start[1]; - k = k / dy; - x = k + start[0]; - if (z < sz && y < sy && x < sx && w < sw) { - j = (((x * sy + y) * sz + z) * sw + w) * size + b; - if (j >= 0 && j < data->data_len) { - ((char *)data->data)[j] = output[i]; + // increase source coordinates + for (d = data->ds.dimensionality - 1; d >= 0; d--) { + c[d]++; + if (c[d] < data->datalayout_chunk[d]) { + break; + } else { + c[d] = 0; + if (d == 0) { // at last, increase bytes + b++; } } } - break; - default: - mylog("invalid dim\n"); // LCOV_EXCL_LINE - return MYSOFA_INTERNAL_ERROR; // LCOV_EXCL_LINE } if (mysofa_seek(reader, store, SEEK_SET) < 0) {