2 * SOFA info utility for inspecting SOFA file metrics and determining HRTF
3 * utility compatible layouts.
5 * Copyright (C) 2018-2019 Christopher Fitzgerald
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Or visit: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
27 #include <string_view>
30 #include "alnumeric.h"
34 #include "sofa-support.h"
38 #include "win_main_utf8.h"
42 using namespace std::string_view_literals
;
43 using uint
= unsigned int;
45 void PrintSofaAttributes(const std::string_view prefix
, MYSOFA_ATTRIBUTE
*attribute
)
49 fmt::println("{}.{}: {}", prefix
, attribute
->name
, attribute
->value
);
50 attribute
= attribute
->next
;
54 void PrintSofaArray(const std::string_view prefix
, MYSOFA_ARRAY
*array
, bool showValues
=true)
56 PrintSofaAttributes(prefix
, array
->attributes
);
59 const auto values
= al::span
{array
->values
, array
->elements
};
60 for(size_t i
{0u};i
< values
.size();++i
)
61 fmt::println("{}[{}]: {:.6f}", prefix
, i
, values
[i
]);
64 fmt::println("{}[...]: <{} values suppressed>", prefix
, array
->elements
);
67 /* Attempts to produce a compatible layout. Most data sets tend to be
68 * uniform and have the same major axis as used by OpenAL Soft's HRTF model.
69 * This will remove outliers and produce a maximally dense layout when
70 * possible. Those sets that contain purely random measurements or use
71 * different major axes will fail.
73 void PrintCompatibleLayout(const al::span
<const float> xyzs
)
77 auto fds
= GetCompatibleLayout(xyzs
);
80 fmt::println("No compatible field layouts in SOFA file.");
85 for(size_t fi
{0u};fi
< fds
.size();++fi
)
87 for(uint ei
{fds
[fi
].mEvStart
};ei
< fds
[fi
].mEvCount
;++ei
)
88 used_elems
+= fds
[fi
].mAzCounts
[ei
];
91 fmt::print("Compatible Layout ({} of {} measurements):\n\ndistance = {:.3f}", used_elems
,
92 xyzs
.size()/3, fds
[0].mDistance
);
93 for(size_t fi
{1u};fi
< fds
.size();fi
++)
94 fmt::print(", {:.3f}", fds
[fi
].mDistance
);
96 fmt::print("\nazimuths = ");
97 for(size_t fi
{0u};fi
< fds
.size();++fi
)
99 for(uint ei
{0u};ei
< fds
[fi
].mEvStart
;++ei
)
100 fmt::print("{}{}", fds
[fi
].mAzCounts
[fds
[fi
].mEvCount
- 1 - ei
], ", ");
101 for(uint ei
{fds
[fi
].mEvStart
};ei
< fds
[fi
].mEvCount
;++ei
)
102 fmt::print("{}{}", fds
[fi
].mAzCounts
[ei
],
103 (ei
< (fds
[fi
].mEvCount
- 1)) ? ", " :
104 (fi
< (fds
.size() - 1)) ? ";\n " : "\n");
108 // Load and inspect the given SOFA file.
109 void SofaInfo(const std::string
&filename
)
112 MySofaHrtfPtr sofa
{mysofa_load(filename
.c_str(), &err
)};
115 fmt::println("Error: Could not load source file '{}' ({}).", filename
,
120 /* NOTE: Some valid SOFA files are failing this check. */
121 err
= mysofa_check(sofa
.get());
123 fmt::println("Warning: Supposedly malformed source file '{}' ({}).", filename
,
126 mysofa_tocartesian(sofa
.get());
128 PrintSofaAttributes("Info", sofa
->attributes
);
130 fmt::println("Measurements: {}", sofa
->M
);
131 fmt::println("Receivers: {}", sofa
->R
);
132 fmt::println("Emitters: {}", sofa
->E
);
133 fmt::println("Samples: {}", sofa
->N
);
135 PrintSofaArray("SampleRate"sv
, &sofa
->DataSamplingRate
);
136 PrintSofaArray("DataDelay"sv
, &sofa
->DataDelay
);
137 PrintSofaArray("SourcePosition"sv
, &sofa
->SourcePosition
, false);
139 PrintCompatibleLayout(al::span
{sofa
->SourcePosition
.values
, sofa
->M
*3_uz
});
142 int main(al::span
<std::string_view
> args
)
146 fmt::println("Usage: {} <sofa-file>", args
[0]);
150 SofaInfo(std::string
{args
[1]});
157 int main(int argc
, char **argv
)
160 auto args
= std::vector
<std::string_view
>(static_cast<unsigned int>(argc
));
161 std::copy_n(argv
, args
.size(), args
.begin());
162 return main(al::span
{args
});