aboutsummaryrefslogtreecommitdiffstats
path: root/utils/makemhr/makemhr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/makemhr/makemhr.cpp')
-rw-r--r--utils/makemhr/makemhr.cpp300
1 files changed, 149 insertions, 151 deletions
diff --git a/utils/makemhr/makemhr.cpp b/utils/makemhr/makemhr.cpp
index 98e1b73f..0a9b71e7 100644
--- a/utils/makemhr/makemhr.cpp
+++ b/utils/makemhr/makemhr.cpp
@@ -90,6 +90,8 @@
#include "alcomplex.h"
#include "alfstream.h"
+#include "alnumbers.h"
+#include "alnumeric.h"
#include "alspan.h"
#include "alstring.h"
#include "loaddef.h"
@@ -98,61 +100,61 @@
#include "win_main_utf8.h"
-namespace {
-
-using namespace std::placeholders;
-
-} // namespace
-
-#ifndef M_PI
-#define M_PI (3.14159265358979323846)
-#endif
-
-
HrirDataT::~HrirDataT() = default;
-// Head model used for calculating the impulse delays.
-enum HeadModelT {
- HM_NONE,
- HM_DATASET, // Measure the onset from the dataset.
- HM_SPHERE // Calculate the onset using a spherical head model.
+namespace {
+
+struct FileDeleter {
+ void operator()(gsl::owner<FILE*> f) { fclose(f); }
};
+using FilePtr = std::unique_ptr<FILE,FileDeleter>;
+using namespace std::placeholders;
// The epsilon used to maintain signal stability.
-#define EPSILON (1e-9)
+constexpr double Epsilon{1e-9};
// The limits to the FFT window size override on the command line.
-#define MIN_FFTSIZE (65536)
-#define MAX_FFTSIZE (131072)
+constexpr uint MinFftSize{65536};
+constexpr uint MaxFftSize{131072};
// The limits to the equalization range limit on the command line.
-#define MIN_LIMIT (2.0)
-#define MAX_LIMIT (120.0)
+constexpr double MinLimit{2.0};
+constexpr double MaxLimit{120.0};
// The limits to the truncation window size on the command line.
-#define MIN_TRUNCSIZE (16)
-#define MAX_TRUNCSIZE (128)
+constexpr uint MinTruncSize{16};
+constexpr uint MaxTruncSize{128};
// The limits to the custom head radius on the command line.
-#define MIN_CUSTOM_RADIUS (0.05)
-#define MAX_CUSTOM_RADIUS (0.15)
-
-// The defaults for the command line options.
-#define DEFAULT_FFTSIZE (65536)
-#define DEFAULT_EQUALIZE (1)
-#define DEFAULT_SURFACE (1)
-#define DEFAULT_LIMIT (24.0)
-#define DEFAULT_TRUNCSIZE (64)
-#define DEFAULT_HEAD_MODEL (HM_DATASET)
-#define DEFAULT_CUSTOM_RADIUS (0.0)
+constexpr double MinCustomRadius{0.05};
+constexpr double MaxCustomRadius{0.15};
// The maximum propagation delay value supported by OpenAL Soft.
-#define MAX_HRTD (63.0)
+constexpr double MaxHrtd{63.0};
// The OpenAL Soft HRTF format marker. It stands for minimum-phase head
// response protocol 03.
-#define MHR_FORMAT ("MinPHR03")
+constexpr char MHRFormat[] = "MinPHR03"; // NOLINT(*-avoid-c-arrays)
+
+
+// Head model used for calculating the impulse delays.
+enum HeadModelT {
+ HM_NONE,
+ HM_DATASET, // Measure the onset from the dataset.
+ HM_SPHERE, // Calculate the onset using a spherical head model.
+
+ DEFAULT_HEAD_MODEL = HM_DATASET
+};
+
+
+// The defaults for the command line options.
+constexpr uint DefaultFftSize{65536};
+constexpr bool DefaultEqualize{true};
+constexpr bool DefaultSurface{true};
+constexpr double DefaultLimit{24.0};
+constexpr uint DefaultTruncSize{64};
+constexpr double DefaultCustomRadius{0.0};
/* Channel index enums. Mono uses LeftChannel only. */
enum ChannelIndex : uint {
@@ -165,7 +167,7 @@ enum ChannelIndex : uint {
* pattern string are replaced with the replacement string. The result is
* truncated if necessary.
*/
-static std::string StrSubst(al::span<const char> in, const al::span<const char> pat,
+std::string StrSubst(al::span<const char> in, const al::span<const char> pat,
const al::span<const char> rep)
{
std::string ret;
@@ -198,12 +200,12 @@ static std::string StrSubst(al::span<const char> in, const al::span<const char>
*********************/
// Simple clamp routine.
-static double Clamp(const double val, const double lower, const double upper)
+double Clamp(const double val, const double lower, const double upper)
{
return std::min(std::max(val, lower), upper);
}
-static inline uint dither_rng(uint *seed)
+inline uint dither_rng(uint *seed)
{
*seed = *seed * 96314165 + 907633515;
return *seed;
@@ -211,8 +213,8 @@ static inline uint dither_rng(uint *seed)
// Performs a triangular probability density function dither. The input samples
// should be normalized (-1 to +1).
-static void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const double scale,
- const uint count, const uint step, uint *seed)
+void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const double scale,
+ const uint count, const uint step, uint *seed)
{
static constexpr double PRNG_SCALE = 1.0 / std::numeric_limits<uint>::max();
@@ -231,9 +233,11 @@ static void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const do
* of a signal's magnitude response, the imaginary components can be used as
* the angles for minimum-phase reconstruction.
*/
-inline static void Hilbert(const uint n, complex_d *inout)
+inline void Hilbert(const uint n, complex_d *inout)
{ complex_hilbert({inout, n}); }
+} // namespace
+
/* Calculate the magnitude response of the given input. This is used in
* place of phase decomposition, since the phase residuals are discarded for
* minimum phase reconstruction. The mirrored half of the response is also
@@ -244,7 +248,7 @@ void MagnitudeResponse(const uint n, const complex_d *in, double *out)
const uint m = 1 + (n / 2);
uint i;
for(i = 0;i < m;i++)
- out[i] = std::max(std::abs(in[i]), EPSILON);
+ out[i] = std::max(std::abs(in[i]), Epsilon);
}
/* Apply a range limit (in dB) to the given magnitude response. This is used
@@ -295,7 +299,7 @@ static void MinimumPhase(const uint n, double *mags, complex_d *out)
}
Hilbert(n, out);
// Remove any DC offset the filter has.
- mags[0] = EPSILON;
+ mags[0] = Epsilon;
for(i = 0;i < n;i++)
out[i] = std::polar(mags[i], out[i].imag());
}
@@ -313,7 +317,6 @@ static int WriteAscii(const char *out, FILE *fp, const char *filename)
len = strlen(out);
if(fwrite(out, 1, len, fp) != len)
{
- fclose(fp);
fprintf(stderr, "\nError: Bad write to file '%s'.\n", filename);
return 0;
}
@@ -324,13 +327,11 @@ static int WriteAscii(const char *out, FILE *fp, const char *filename)
// loading it from a 32-bit unsigned integer.
static int WriteBin4(const uint bytes, const uint32_t in, FILE *fp, const char *filename)
{
- uint8_t out[4];
- uint i;
-
- for(i = 0;i < bytes;i++)
+ std::array<uint8_t,4> out{};
+ for(uint i{0};i < bytes;i++)
out[i] = (in>>(i*8)) & 0x000000FF;
- if(fwrite(out, 1, bytes, fp) != bytes)
+ if(fwrite(out.data(), 1, bytes, fp) != bytes)
{
fprintf(stderr, "\nError: Bad write to file '%s'.\n", filename);
return 0;
@@ -345,34 +346,34 @@ static int StoreMhr(const HrirDataT *hData, const char *filename)
const uint n{hData->mIrPoints};
uint dither_seed{22222};
uint fi, ei, ai, i;
- FILE *fp;
- if((fp=fopen(filename, "wb")) == nullptr)
+ FilePtr fp{fopen(filename, "wb")};
+ if(!fp)
{
fprintf(stderr, "\nError: Could not open MHR file '%s'.\n", filename);
return 0;
}
- if(!WriteAscii(MHR_FORMAT, fp, filename))
+ if(!WriteAscii(MHRFormat, fp.get(), filename))
return 0;
- if(!WriteBin4(4, hData->mIrRate, fp, filename))
+ if(!WriteBin4(4, hData->mIrRate, fp.get(), filename))
return 0;
- if(!WriteBin4(1, static_cast<uint32_t>(hData->mChannelType), fp, filename))
+ if(!WriteBin4(1, static_cast<uint32_t>(hData->mChannelType), fp.get(), filename))
return 0;
- if(!WriteBin4(1, hData->mIrPoints, fp, filename))
+ if(!WriteBin4(1, hData->mIrPoints, fp.get(), filename))
return 0;
- if(!WriteBin4(1, static_cast<uint>(hData->mFds.size()), fp, filename))
+ if(!WriteBin4(1, static_cast<uint>(hData->mFds.size()), fp.get(), filename))
return 0;
for(fi = static_cast<uint>(hData->mFds.size()-1);fi < hData->mFds.size();fi--)
{
auto fdist = static_cast<uint32_t>(std::round(1000.0 * hData->mFds[fi].mDistance));
- if(!WriteBin4(2, fdist, fp, filename))
+ if(!WriteBin4(2, fdist, fp.get(), filename))
return 0;
- if(!WriteBin4(1, static_cast<uint32_t>(hData->mFds[fi].mEvs.size()), fp, filename))
+ if(!WriteBin4(1, static_cast<uint32_t>(hData->mFds[fi].mEvs.size()), fp.get(), filename))
return 0;
for(ei = 0;ei < hData->mFds[fi].mEvs.size();ei++)
{
const auto &elev = hData->mFds[fi].mEvs[ei];
- if(!WriteBin4(1, static_cast<uint32_t>(elev.mAzs.size()), fp, filename))
+ if(!WriteBin4(1, static_cast<uint32_t>(elev.mAzs.size()), fp.get(), filename))
return 0;
}
}
@@ -387,15 +388,15 @@ static int StoreMhr(const HrirDataT *hData, const char *filename)
for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzs.size();ai++)
{
HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
- double out[2 * MAX_TRUNCSIZE];
+ std::array<double,MaxTruncSize*2_uz> out{};
- TpdfDither(out, azd->mIrs[0], scale, n, channels, &dither_seed);
+ TpdfDither(out.data(), azd->mIrs[0], scale, n, channels, &dither_seed);
if(hData->mChannelType == CT_STEREO)
- TpdfDither(out+1, azd->mIrs[1], scale, n, channels, &dither_seed);
+ TpdfDither(out.data()+1, azd->mIrs[1], scale, n, channels, &dither_seed);
for(i = 0;i < (channels * n);i++)
{
const auto v = static_cast<int>(Clamp(out[i], -scale-1.0, scale));
- if(!WriteBin4(bps, static_cast<uint32_t>(v), fp, filename))
+ if(!WriteBin4(bps, static_cast<uint32_t>(v), fp.get(), filename))
return 0;
}
}
@@ -410,16 +411,15 @@ static int StoreMhr(const HrirDataT *hData, const char *filename)
for(const auto &azd : hData->mFds[fi].mEvs[ei].mAzs)
{
auto v = static_cast<uint>(std::round(azd.mDelays[0]*DelayPrecScale));
- if(!WriteBin4(1, v, fp, filename)) return 0;
+ if(!WriteBin4(1, v, fp.get(), filename)) return 0;
if(hData->mChannelType == CT_STEREO)
{
v = static_cast<uint>(std::round(azd.mDelays[1]*DelayPrecScale));
- if(!WriteBin4(1, v, fp, filename)) return 0;
+ if(!WriteBin4(1, v, fp.get(), filename)) return 0;
}
}
}
}
- fclose(fp);
return 1;
}
@@ -434,21 +434,18 @@ static int StoreMhr(const HrirDataT *hData, const char *filename)
*/
static void BalanceFieldMagnitudes(const HrirDataT *hData, const uint channels, const uint m)
{
- double maxMags[MAX_FD_COUNT];
- uint fi, ei, ti, i;
-
+ std::array<double,MAX_FD_COUNT> maxMags{};
double maxMag{0.0};
- for(fi = 0;fi < hData->mFds.size();fi++)
- {
- maxMags[fi] = 0.0;
- for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvs.size();ei++)
+ for(size_t fi{0};fi < hData->mFds.size();++fi)
+ {
+ for(size_t ei{hData->mFds[fi].mEvStart};ei < hData->mFds[fi].mEvs.size();++ei)
{
for(const auto &azd : hData->mFds[fi].mEvs[ei].mAzs)
{
- for(ti = 0;ti < channels;ti++)
+ for(size_t ti{0};ti < channels;++ti)
{
- for(i = 0;i < m;i++)
+ for(size_t i{0};i < m;++i)
maxMags[fi] = std::max(azd.mIrs[ti][i], maxMags[fi]);
}
}
@@ -457,17 +454,17 @@ static void BalanceFieldMagnitudes(const HrirDataT *hData, const uint channels,
maxMag = std::max(maxMags[fi], maxMag);
}
- for(fi = 0;fi < hData->mFds.size();fi++)
+ for(size_t fi{0};fi < hData->mFds.size();++fi)
{
const double magFactor{maxMag / maxMags[fi]};
- for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvs.size();ei++)
+ for(size_t ei{hData->mFds[fi].mEvStart};ei < hData->mFds[fi].mEvs.size();++ei)
{
for(const auto &azd : hData->mFds[fi].mEvs[ei].mAzs)
{
- for(ti = 0;ti < channels;ti++)
+ for(size_t ti{0};ti < channels;++ti)
{
- for(i = 0;i < m;i++)
+ for(size_t i{0};i < m;++i)
azd.mIrs[ti][i] *= magFactor;
}
}
@@ -499,17 +496,17 @@ static void CalculateDfWeights(const HrirDataT *hData, double *weights)
outerRa = 10.0f;
const double raPowDiff{std::pow(outerRa, 3.0) - std::pow(innerRa, 3.0)};
- evs = M_PI / 2.0 / static_cast<double>(hData->mFds[fi].mEvs.size() - 1);
+ evs = al::numbers::pi / 2.0 / static_cast<double>(hData->mFds[fi].mEvs.size() - 1);
for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvs.size();ei++)
{
const auto &elev = hData->mFds[fi].mEvs[ei];
// For each elevation, calculate the upper and lower limits of
// the patch band.
ev = elev.mElevation;
- lowerEv = std::max(-M_PI / 2.0, ev - evs);
- upperEv = std::min(M_PI / 2.0, ev + evs);
+ lowerEv = std::max(-al::numbers::pi / 2.0, ev - evs);
+ upperEv = std::min(al::numbers::pi / 2.0, ev + evs);
// Calculate the surface area of the patch band.
- solidAngle = 2.0 * M_PI * (std::sin(upperEv) - std::sin(lowerEv));
+ solidAngle = 2.0 * al::numbers::pi * (std::sin(upperEv) - std::sin(lowerEv));
// Then the volume of the extruded patch band.
solidVolume = solidAngle * raPowDiff / 3.0;
// Each weight is the volume of one extruded patch.
@@ -539,7 +536,7 @@ static void CalculateDiffuseFieldAverage(const HrirDataT *hData, const uint chan
const int weighted, const double limit, double *dfa)
{
std::vector<double> weights(hData->mFds.size() * MAX_EV_COUNT);
- uint count, ti, fi, ei, i, ai;
+ uint count;
if(weighted)
{
@@ -553,42 +550,42 @@ static void CalculateDiffuseFieldAverage(const HrirDataT *hData, const uint chan
// If coverage weighting is not used, the weights still need to be
// averaged by the number of existing HRIRs.
count = hData->mIrCount;
- for(fi = 0;fi < hData->mFds.size();fi++)
+ for(size_t fi{0};fi < hData->mFds.size();++fi)
{
- for(ei = 0;ei < hData->mFds[fi].mEvStart;ei++)
+ for(size_t ei{0};ei < hData->mFds[fi].mEvStart;++ei)
count -= static_cast<uint>(hData->mFds[fi].mEvs[ei].mAzs.size());
}
weight = 1.0 / count;
- for(fi = 0;fi < hData->mFds.size();fi++)
+ for(size_t fi{0};fi < hData->mFds.size();++fi)
{
- for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvs.size();ei++)
+ for(size_t ei{hData->mFds[fi].mEvStart};ei < hData->mFds[fi].mEvs.size();++ei)
weights[(fi * MAX_EV_COUNT) + ei] = weight;
}
}
- for(ti = 0;ti < channels;ti++)
+ for(size_t ti{0};ti < channels;++ti)
{
- for(i = 0;i < m;i++)
+ for(size_t i{0};i < m;++i)
dfa[(ti * m) + i] = 0.0;
- for(fi = 0;fi < hData->mFds.size();fi++)
+ for(size_t fi{0};fi < hData->mFds.size();++fi)
{
- for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvs.size();ei++)
+ for(size_t ei{hData->mFds[fi].mEvStart};ei < hData->mFds[fi].mEvs.size();++ei)
{
- for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzs.size();ai++)
+ for(size_t ai{0};ai < hData->mFds[fi].mEvs[ei].mAzs.size();++ai)
{
HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
// Get the weight for this HRIR's contribution.
double weight = weights[(fi * MAX_EV_COUNT) + ei];
// Add this HRIR's weighted power average to the total.
- for(i = 0;i < m;i++)
+ for(size_t i{0};i < m;++i)
dfa[(ti * m) + i] += weight * azd->mIrs[ti][i] * azd->mIrs[ti][i];
}
}
}
// Finish the average calculation and keep it from being too small.
- for(i = 0;i < m;i++)
- dfa[(ti * m) + i] = std::max(sqrt(dfa[(ti * m) + i]), EPSILON);
+ for(size_t i{0};i < m;++i)
+ dfa[(ti * m) + i] = std::max(sqrt(dfa[(ti * m) + i]), Epsilon);
// Apply a limit to the magnitude range of the diffuse-field average
// if desired.
if(limit > 0.0)
@@ -600,17 +597,15 @@ static void CalculateDiffuseFieldAverage(const HrirDataT *hData, const uint chan
// set using the given average response.
static void DiffuseFieldEqualize(const uint channels, const uint m, const double *dfa, const HrirDataT *hData)
{
- uint ti, fi, ei, i;
-
- for(fi = 0;fi < hData->mFds.size();fi++)
+ for(size_t fi{0};fi < hData->mFds.size();++fi)
{
- for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvs.size();ei++)
+ for(size_t ei{hData->mFds[fi].mEvStart};ei < hData->mFds[fi].mEvs.size();++ei)
{
for(auto &azd : hData->mFds[fi].mEvs[ei].mAzs)
{
- for(ti = 0;ti < channels;ti++)
+ for(size_t ti{0};ti < channels;++ti)
{
- for(i = 0;i < m;i++)
+ for(size_t i{0};i < m;++i)
azd.mIrs[ti][i] /= dfa[(ti * m) + i];
}
}
@@ -624,7 +619,8 @@ static void DiffuseFieldEqualize(const uint channels, const uint m, const double
*/
static void CalcAzIndices(const HrirFdT &field, const uint ei, const double az, uint *a0, uint *a1, double *af)
{
- double f{(2.0*M_PI + az) * static_cast<double>(field.mEvs[ei].mAzs.size()) / (2.0*M_PI)};
+ double f{(2.0*al::numbers::pi + az) * static_cast<double>(field.mEvs[ei].mAzs.size()) /
+ (2.0*al::numbers::pi)};
const uint i{static_cast<uint>(f) % static_cast<uint>(field.mEvs[ei].mAzs.size())};
f -= std::floor(f);
@@ -674,7 +670,7 @@ static void SynthesizeOnsets(HrirDataT *hData)
* the mirrored elevation to find the indices for the polar
* opposite position (may need blending).
*/
- const double az{field.mEvs[ei].mAzs[ai].mAzimuth + M_PI};
+ const double az{field.mEvs[ei].mAzs[ai].mAzimuth + al::numbers::pi};
CalcAzIndices(field, topElev, az, &a0, &a1, &af);
/* Blend the delays, and again, swap the ears. */
@@ -706,8 +702,8 @@ static void SynthesizeOnsets(HrirDataT *hData)
* measurement).
*/
double az{field.mEvs[ei].mAzs[ai].mAzimuth};
- if(az <= M_PI) az = M_PI - az;
- else az = (M_PI*2.0)-az + M_PI;
+ if(az <= al::numbers::pi) az = al::numbers::pi - az;
+ else az = (al::numbers::pi*2.0)-az + al::numbers::pi;
CalcAzIndices(field, topElev, az, &a0, &a1, &af);
field.mEvs[ei].mAzs[ai].mDelays[0] = Lerp(
@@ -735,12 +731,12 @@ static void SynthesizeOnsets(HrirDataT *hData)
double az{field.mEvs[ei].mAzs[ai].mAzimuth};
CalcAzIndices(field, upperElevReal, az, &a0, &a1, &af0);
CalcAzIndices(field, lowerElevFake, az, &a2, &a3, &af1);
- double blend[4]{
+ std::array<double,4> blend{{
(1.0-ef) * (1.0-af0),
(1.0-ef) * ( af0),
( ef) * (1.0-af1),
( ef) * ( af1)
- };
+ }};
for(uint ti{0u};ti < channels;ti++)
{
@@ -785,7 +781,7 @@ static void SynthesizeHrirs(HrirDataT *hData)
* and vice-versa, this produces a decent phantom-center response
* underneath the head.
*/
- CalcAzIndices(field, oi, ((ti==0) ? -M_PI : M_PI) / 2.0, &a0, &a1, &af);
+ CalcAzIndices(field, oi, al::numbers::pi / ((ti==0) ? -2.0 : 2.0), &a0, &a1, &af);
for(uint i{0u};i < m;i++)
{
field.mEvs[0].mAzs[0].mIrs[ti][i] = Lerp(field.mEvs[oi].mAzs[a0].mIrs[ti][i],
@@ -797,7 +793,7 @@ static void SynthesizeHrirs(HrirDataT *hData)
{
const double of{static_cast<double>(ei) / field.mEvStart};
const double b{(1.0 - of) * beta};
- double lp[4]{};
+ std::array<double,4> lp{};
/* Calculate a low-pass filter to simulate body occlusion. */
lp[0] = Lerp(1.0, lp[0], b);
@@ -842,7 +838,7 @@ static void SynthesizeHrirs(HrirDataT *hData)
}
}
const double b{beta};
- double lp[4]{};
+ std::array<double,4> lp{};
lp[0] = Lerp(1.0, lp[0], b);
lp[1] = Lerp(lp[0], lp[1], b);
lp[2] = Lerp(lp[1], lp[2], b);
@@ -877,10 +873,10 @@ static void SynthesizeHrirs(HrirDataT *hData)
*/
struct HrirReconstructor {
std::vector<double*> mIrs;
- std::atomic<size_t> mCurrent;
- std::atomic<size_t> mDone;
- uint mFftSize;
- uint mIrPoints;
+ std::atomic<size_t> mCurrent{};
+ std::atomic<size_t> mDone{};
+ uint mFftSize{};
+ uint mIrPoints{};
void Worker()
{
@@ -888,7 +884,7 @@ struct HrirReconstructor {
auto mags = std::vector<double>(mFftSize);
size_t m{(mFftSize/2) + 1};
- while(1)
+ while(true)
{
/* Load the current index to process. */
size_t idx{mCurrent.load()};
@@ -907,7 +903,7 @@ struct HrirReconstructor {
* time-domain response.
*/
for(size_t i{0};i < m;++i)
- mags[i] = std::max(mIrs[idx][i], EPSILON);
+ mags[i] = std::max(mIrs[idx][i], Epsilon);
MinimumPhase(mFftSize, mags.data(), h.data());
FftInverse(mFftSize, h.data());
for(uint i{0u};i < mIrPoints;++i)
@@ -991,7 +987,7 @@ static void NormalizeHrirs(HrirDataT *hData)
return LevelPair{std::max(current.amp, levels.amp), std::max(current.rms, levels.rms)};
};
auto measure_azi = [channels,mesasure_channel](const LevelPair levels, const HrirAzT &azi)
- { return std::accumulate(azi.mIrs, azi.mIrs+channels, levels, mesasure_channel); };
+ { return std::accumulate(azi.mIrs.begin(), azi.mIrs.begin()+channels, levels, mesasure_channel); };
auto measure_elev = [measure_azi](const LevelPair levels, const HrirEvT &elev)
{ return std::accumulate(elev.mAzs.cbegin(), elev.mAzs.cend(), levels, measure_azi); };
auto measure_field = [measure_elev](const LevelPair levels, const HrirFdT &field)
@@ -1018,7 +1014,7 @@ static void NormalizeHrirs(HrirDataT *hData)
auto proc_channel = [irSize,factor](double *ir)
{ std::transform(ir, ir+irSize, ir, [factor](double s){ return s * factor; }); };
auto proc_azi = [channels,proc_channel](HrirAzT &azi)
- { std::for_each(azi.mIrs, azi.mIrs+channels, proc_channel); };
+ { std::for_each(azi.mIrs.begin(), azi.mIrs.begin()+channels, proc_channel); };
auto proc_elev = [proc_azi](HrirEvT &elev)
{ std::for_each(elev.mAzs.begin(), elev.mAzs.end(), proc_azi); };
auto proc1_field = [proc_elev](HrirFdT &field)
@@ -1035,7 +1031,7 @@ static double CalcLTD(const double ev, const double az, const double rad, const
azp = std::asin(std::cos(ev) * std::sin(az));
dlp = std::sqrt((dist*dist) + (rad*rad) + (2.0*dist*rad*sin(azp)));
l = std::sqrt((dist*dist) - (rad*rad));
- al = (0.5 * M_PI) + azp;
+ al = (0.5 * al::numbers::pi) + azp;
if(dlp > l)
dlp = l + (rad * (al - std::acos(rad / dist)));
return dlp / 343.3;
@@ -1103,10 +1099,10 @@ static void CalculateHrtds(const HeadModelT model, const double radius, HrirData
}
}
}
- if(maxHrtd > MAX_HRTD)
+ if(maxHrtd > MaxHrtd)
{
- fprintf(stdout, " Scaling for max delay of %f samples to %f\n...\n", maxHrtd, MAX_HRTD);
- const double scale{MAX_HRTD / maxHrtd};
+ fprintf(stdout, " Scaling for max delay of %f samples to %f\n...\n", maxHrtd, MaxHrtd);
+ const double scale{MaxHrtd / maxHrtd};
for(auto &field : hData->mFds)
{
for(auto &elev : field.mEvs)
@@ -1153,11 +1149,12 @@ bool PrepareHrirData(const al::span<const double> distances,
{
uint azCount = azCounts[fi][ei];
- hData->mFds[fi].mEvs[ei].mElevation = -M_PI / 2.0 + M_PI * ei / (evCounts[fi] - 1);
+ hData->mFds[fi].mEvs[ei].mElevation = -al::numbers::pi / 2.0 + al::numbers::pi * ei /
+ (evCounts[fi] - 1);
hData->mFds[fi].mEvs[ei].mAzs = {&hData->mAzsBase[azTotal], azCount};
for(uint ai{0};ai < azCount;ai++)
{
- hData->mFds[fi].mEvs[ei].mAzs[ai].mAzimuth = 2.0 * M_PI * ai / azCount;
+ hData->mFds[fi].mEvs[ei].mAzs[ai].mAzimuth = 2.0 * al::numbers::pi * ai / azCount;
hData->mFds[fi].mEvs[ei].mAzs[ai].mIndex = azTotal + ai;
hData->mFds[fi].mEvs[ei].mAzs[ai].mDelays[0] = 0.0;
hData->mFds[fi].mEvs[ei].mAzs[ai].mDelays[1] = 0.0;
@@ -1199,10 +1196,10 @@ static int ProcessDefinition(const char *inName, const uint outRate, const Chann
return 0;
}
- char startbytes[4]{};
- input->read(startbytes, sizeof(startbytes));
+ std::array<char,4> startbytes{};
+ input->read(startbytes.data(), startbytes.size());
std::streamsize startbytecount{input->gcount()};
- if(startbytecount != sizeof(startbytes) || !input->good())
+ if(startbytecount != startbytes.size() || !input->good())
{
fprintf(stderr, "Error: Could not read input file '%s'\n", inName);
return 0;
@@ -1219,7 +1216,8 @@ static int ProcessDefinition(const char *inName, const uint outRate, const Chann
else
{
fprintf(stdout, "Reading HRIR definition from %s...\n", inName);
- if(!LoadDefInput(*input, startbytes, startbytecount, inName, fftSize, truncSize, outRate, chanMode, &hData))
+ if(!LoadDefInput(*input, startbytes.data(), startbytecount, inName, fftSize, truncSize,
+ outRate, chanMode, &hData))
return 0;
}
}
@@ -1228,7 +1226,7 @@ static int ProcessDefinition(const char *inName, const uint outRate, const Chann
{
uint c{(hData.mChannelType == CT_STEREO) ? 2u : 1u};
uint m{hData.mFftSize/2u + 1u};
- auto dfa = std::vector<double>(c * m);
+ auto dfa = std::vector<double>(size_t{c} * m);
if(hData.mFds.size() > 1)
{
@@ -1264,7 +1262,7 @@ static int ProcessDefinition(const char *inName, const uint outRate, const Chann
fprintf(stdout, "Normalizing final HRIRs...\n");
NormalizeHrirs(&hData);
fprintf(stdout, "Calculating impulse delays...\n");
- CalculateHrtds(model, (radius > DEFAULT_CUSTOM_RADIUS) ? radius : hData.mRadius, &hData);
+ CalculateHrtds(model, (radius > DefaultCustomRadius) ? radius : hData.mRadius, &hData);
const auto rateStr = std::to_string(hData.mIrRate);
const auto expName = StrSubst({outName, strlen(outName)}, {"%r", 2},
@@ -1283,13 +1281,13 @@ static void PrintHelp(const char *argv0, FILE *ofile)
fprintf(ofile, " right ear.\n");
fprintf(ofile, " -a Change the data set to single field, using the farthest field.\n");
fprintf(ofile, " -j <threads> Number of threads used to process HRIRs (default: 2).\n");
- fprintf(ofile, " -f <points> Override the FFT window size (default: %u).\n", DEFAULT_FFTSIZE);
- fprintf(ofile, " -e {on|off} Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off"));
- fprintf(ofile, " -s {on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off"));
+ fprintf(ofile, " -f <points> Override the FFT window size (default: %u).\n", DefaultFftSize);
+ fprintf(ofile, " -e {on|off} Toggle diffuse-field equalization (default: %s).\n", (DefaultEqualize ? "on" : "off"));
+ fprintf(ofile, " -s {on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DefaultSurface ? "on" : "off"));
fprintf(ofile, " -l {<dB>|none} Specify a limit to the magnitude range of the diffuse-field\n");
- fprintf(ofile, " average (default: %.2f).\n", DEFAULT_LIMIT);
+ fprintf(ofile, " average (default: %.2f).\n", DefaultLimit);
fprintf(ofile, " -w <points> Specify the size of the truncation window that's applied\n");
- fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE);
+ fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DefaultTruncSize);
fprintf(ofile, " -d {dataset| Specify the model used for calculating the head-delay timing\n");
fprintf(ofile, " sphere} values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere"));
fprintf(ofile, " -c <radius> Use a customized head radius measured to-ear in meters.\n");
@@ -1324,14 +1322,14 @@ int main(int argc, char *argv[])
outName = "./oalsoft_hrtf_%r.mhr";
outRate = 0;
chanMode = CM_AllowStereo;
- fftSize = DEFAULT_FFTSIZE;
- equalize = DEFAULT_EQUALIZE;
- surface = DEFAULT_SURFACE;
- limit = DEFAULT_LIMIT;
+ fftSize = DefaultFftSize;
+ equalize = DefaultEqualize;
+ surface = DefaultSurface;
+ limit = DefaultLimit;
numThreads = 2;
- truncSize = DEFAULT_TRUNCSIZE;
+ truncSize = DefaultTruncSize;
model = DEFAULT_HEAD_MODEL;
- radius = DEFAULT_CUSTOM_RADIUS;
+ radius = DefaultCustomRadius;
farfield = false;
while((opt=getopt(argc, argv, "r:maj:f:e:s:l:w:d:c:e:i:o:h")) != -1)
@@ -1368,9 +1366,9 @@ int main(int argc, char *argv[])
case 'f':
fftSize = static_cast<uint>(strtoul(optarg, &end, 10));
- if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MIN_FFTSIZE || fftSize > MAX_FFTSIZE)
+ if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MinFftSize || fftSize > MaxFftSize)
{
- fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected a power-of-two between %u to %u.\n", optarg, opt, MIN_FFTSIZE, MAX_FFTSIZE);
+ fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected a power-of-two between %u to %u.\n", optarg, opt, MinFftSize, MaxFftSize);
exit(EXIT_FAILURE);
}
break;
@@ -1405,9 +1403,9 @@ int main(int argc, char *argv[])
else
{
limit = strtod(optarg, &end);
- if(end[0] != '\0' || limit < MIN_LIMIT || limit > MAX_LIMIT)
+ if(end[0] != '\0' || limit < MinLimit || limit > MaxLimit)
{
- fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.0f to %.0f.\n", optarg, opt, MIN_LIMIT, MAX_LIMIT);
+ fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.0f to %.0f.\n", optarg, opt, MinLimit, MaxLimit);
exit(EXIT_FAILURE);
}
}
@@ -1415,9 +1413,9 @@ int main(int argc, char *argv[])
case 'w':
truncSize = static_cast<uint>(strtoul(optarg, &end, 10));
- if(end[0] != '\0' || truncSize < MIN_TRUNCSIZE || truncSize > MAX_TRUNCSIZE)
+ if(end[0] != '\0' || truncSize < MinTruncSize || truncSize > MaxTruncSize)
{
- fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %u to %u.\n", optarg, opt, MIN_TRUNCSIZE, MAX_TRUNCSIZE);
+ fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %u to %u.\n", optarg, opt, MinTruncSize, MaxTruncSize);
exit(EXIT_FAILURE);
}
break;
@@ -1436,9 +1434,9 @@ int main(int argc, char *argv[])
case 'c':
radius = strtod(optarg, &end);
- if(end[0] != '\0' || radius < MIN_CUSTOM_RADIUS || radius > MAX_CUSTOM_RADIUS)
+ if(end[0] != '\0' || radius < MinCustomRadius || radius > MaxCustomRadius)
{
- fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.2f to %.2f.\n", optarg, opt, MIN_CUSTOM_RADIUS, MAX_CUSTOM_RADIUS);
+ fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.2f to %.2f.\n", optarg, opt, MinCustomRadius, MaxCustomRadius);
exit(EXIT_FAILURE);
}
break;