#include "../hdf/reader.h"
#include "mysofa.h"
#include "mysofa_export.h"
#include "tools.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
static int compareValues(struct MYSOFA_ARRAY *array, const float *compare,
int elements, int size) {
int i, j;
if (array->values == NULL || array->elements != elements * size)
return 0;
for (j = 0; j < array->elements;)
for (i = 0; i < elements; i++, j++)
if (!fequals(array->values[j], compare[i]))
return 0;
return 1;
}
static const float array000[] = {0, 0, 0};
static const float array001[] = {0, 0, 1};
static const float array100[] = {1, 0, 0};
MYSOFA_EXPORT int mysofa_check(struct MYSOFA_HRTF *hrtf) {
if (!verifyAttribute(hrtf->attributes, "Conventions", "SOFA") ||
!verifyAttribute(hrtf->attributes, "SOFAConventions",
"SimpleFreeFieldHRIR") ||
!verifyAttribute(hrtf->attributes, "DataType", "FIR"))
return MYSOFA_INVALID_ATTRIBUTES;
if (hrtf->C != 3 || hrtf->I != 1 || hrtf->E != 1 || hrtf->R != 2 ||
hrtf->M == 0)
return MYSOFA_INVALID_DIMENSIONS;
if (hrtf->ListenerView.values) {
int m = 1;
if (!verifyAttribute(hrtf->ListenerView.attributes, "DIMENSION_LIST",
"I,C")) {
if (!verifyAttribute(hrtf->ListenerView.attributes, "DIMENSION_LIST",
"M,C")) {
return MYSOFA_INVALID_DIMENSION_LIST; }
m = hrtf->M;
}
if (verifyAttribute(hrtf->ListenerView.attributes, "Type", "cartesian")) {
if (!compareValues(&hrtf->ListenerView, array100, 3, m))
return MYSOFA_INVALID_FORMAT; } else if (verifyAttribute(hrtf->ListenerView.attributes, "Type",
"spherical")) {
if (!compareValues(&hrtf->ListenerView, array001, 3, m))
return MYSOFA_INVALID_FORMAT; } else
return MYSOFA_INVALID_COORDINATE_TYPE; }
#if 0#endif
int m = 1;
if (!verifyAttribute(hrtf->EmitterPosition.attributes, "DIMENSION_LIST",
"E,C,I")) {
if (!verifyAttribute(hrtf->EmitterPosition.attributes, "DIMENSION_LIST",
"E,C,M")) {
return MYSOFA_ONLY_EMITTER_WITH_ECI_SUPPORTED; }
m = hrtf->M;
}
if (!compareValues(&hrtf->EmitterPosition, array000, 3, m))
return MYSOFA_ONLY_EMITTER_WITH_ECI_SUPPORTED;
if (hrtf->DataDelay.values) {
if (!verifyAttribute(hrtf->DataDelay.attributes, "DIMENSION_LIST", "I,R") &&
!verifyAttribute(hrtf->DataDelay.attributes, "DIMENSION_LIST", "M,R"))
return MYSOFA_ONLY_DELAYS_WITH_IR_OR_MR_SUPPORTED; }
if (!verifyAttribute(hrtf->DataSamplingRate.attributes, "DIMENSION_LIST",
"I"))
return MYSOFA_ONLY_THE_SAME_SAMPLING_RATE_SUPPORTED;
if (verifyAttribute(hrtf->ReceiverPosition.attributes, "DIMENSION_LIST",
"R,C,I")) {
} else if (verifyAttribute(hrtf->ReceiverPosition.attributes,
"DIMENSION_LIST", "R,C,M")) {
if (hrtf->ReceiverPosition.elements != hrtf->C * hrtf->R * hrtf->M)
return MYSOFA_INVALID_RECEIVER_POSITIONS;
for (int i = 0; i < hrtf->C * hrtf->R; i++) {
int offset = i * hrtf->M;
double receiverPosition = hrtf->ReceiverPosition.values[offset];
for (int j = 1; j < hrtf->M; j++)
if (!fequals(receiverPosition,
hrtf->ReceiverPosition.values[offset + j]))
return MYSOFA_RECEIVERS_WITH_RCI_SUPPORTED; }
} else {
return MYSOFA_RECEIVERS_WITH_RCI_SUPPORTED; }
if (!verifyAttribute(hrtf->ReceiverPosition.attributes, "Type", "cartesian"))
return MYSOFA_RECEIVERS_WITH_CARTESIAN_SUPPORTED;
if (hrtf->ReceiverPosition.elements < hrtf->C * hrtf->R ||
fabs(hrtf->ReceiverPosition.values[0]) >= 0.02f || fabs(hrtf->ReceiverPosition.values[2]) >= 0.02f ||
fabs(hrtf->ReceiverPosition.values[3]) >= 0.02f ||
fabs(hrtf->ReceiverPosition.values[5]) >= 0.02f)
{
return MYSOFA_INVALID_RECEIVER_POSITIONS; }
if (fabs(hrtf->ReceiverPosition.values[4] +
hrtf->ReceiverPosition.values[1]) >= 0.02f)
return MYSOFA_INVALID_RECEIVER_POSITIONS; if (hrtf->ReceiverPosition.values[1] < 0) {
if (!verifyAttribute(hrtf->attributes, "APIName",
"ARI SOFA API for Matlab/Octave"))
return MYSOFA_INVALID_RECEIVER_POSITIONS;
const char *version = mysofa_getAttribute(hrtf->attributes, "APIVersion");
if (version == NULL)
return MYSOFA_INVALID_RECEIVER_POSITIONS;
int a, b, c;
int res = sscanf(version, "%d.%d.%d", &a, &b, &c);
if (res != 3)
return MYSOFA_INVALID_RECEIVER_POSITIONS; if (a > 1)
return MYSOFA_INVALID_RECEIVER_POSITIONS; if (a == 1 && b > 1)
return MYSOFA_INVALID_RECEIVER_POSITIONS; if (a == 1 && b == 1 && c > 0)
return MYSOFA_INVALID_RECEIVER_POSITIONS;
if (hrtf->ReceiverPosition.values[1] >= 0)
return MYSOFA_INVALID_RECEIVER_POSITIONS;
mylog("WARNING: SOFA file is written with wrong receiver positions. %d "
"%d.%d.%d %f<>%f\n",
res, a, b, c, hrtf->ReceiverPosition.values[1],
hrtf->ReceiverPosition.values[4]);
}
if (!verifyAttribute(hrtf->SourcePosition.attributes, "DIMENSION_LIST",
"M,C"))
return MYSOFA_ONLY_SOURCES_WITH_MC_SUPPORTED;
return MYSOFA_OK;
}