Avoid dynamic vectors in AmbDecConf
Also add a bit more sanity checking
This commit is contained in:
+3
-3
@@ -66,10 +66,10 @@ BFormatDec::BFormatDec(const AmbDecConf *conf, const bool allow_2band, const siz
|
||||
if(!(conf->ChanMask&(1u<<acn))) continue;
|
||||
const size_t order{AmbiIndex::OrderFromChannel[acn]};
|
||||
const float gain{conf->HFOrderGain[order] / coeff_scale[acn]};
|
||||
for(size_t i{0u};i < conf->Speakers.size();++i)
|
||||
for(size_t i{0u};i < conf->NumSpeakers;++i)
|
||||
{
|
||||
const size_t chanidx{chanmap[i]};
|
||||
mChannelDec[j].mGains.Single[chanidx] = conf->HFMatrix[i][k] * gain;
|
||||
mChannelDec[j].mGains.Single[chanidx] = conf->Matrix[i][k] * gain;
|
||||
}
|
||||
++k;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ BFormatDec::BFormatDec(const AmbDecConf *conf, const bool allow_2band, const siz
|
||||
const size_t order{AmbiIndex::OrderFromChannel[acn]};
|
||||
const float hfGain{conf->HFOrderGain[order] * ratio / coeff_scale[acn]};
|
||||
const float lfGain{conf->LFOrderGain[order] / ratio / coeff_scale[acn]};
|
||||
for(size_t i{0u};i < conf->Speakers.size();++i)
|
||||
for(size_t i{0u};i < conf->NumSpeakers;++i)
|
||||
{
|
||||
const size_t chanidx{chanmap[i]};
|
||||
mChannelDec[j].mGains.Dual[sHFBand][chanidx] = conf->HFMatrix[i][k] * hfGain;
|
||||
|
||||
+15
-14
@@ -208,9 +208,10 @@ bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALuint (&speakerm
|
||||
ERR("Failed to lookup AmbDec speaker label %s\n", speaker.Name.c_str());
|
||||
return chidx;
|
||||
};
|
||||
std::transform(conf->Speakers.begin(), conf->Speakers.end(), std::begin(speakermap), map_spkr);
|
||||
std::transform(conf->Speakers.get(), conf->Speakers.get()+conf->NumSpeakers,
|
||||
std::begin(speakermap), map_spkr);
|
||||
/* Return success if no invalid entries are found. */
|
||||
auto spkrmap_end = std::begin(speakermap) + conf->Speakers.size();
|
||||
auto spkrmap_end = std::begin(speakermap) + conf->NumSpeakers;
|
||||
return std::find(std::begin(speakermap), spkrmap_end, INVALID_CHANNEL_INDEX) == spkrmap_end;
|
||||
}
|
||||
|
||||
@@ -238,8 +239,8 @@ void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf,
|
||||
{
|
||||
auto get_max = std::bind(maxf, _1,
|
||||
std::bind(std::mem_fn(&AmbDecConf::SpeakerConf::Distance), _2));
|
||||
const float maxdist{std::accumulate(conf->Speakers.begin(), conf->Speakers.end(), 0.0f,
|
||||
get_max)};
|
||||
const float maxdist{std::accumulate(conf->Speakers.get(),
|
||||
conf->Speakers.get()+conf->NumSpeakers, 0.0f, get_max)};
|
||||
|
||||
const char *devname{device->DeviceName.c_str()};
|
||||
if(!GetConfigValueBool(devname, "decoder", "distance-comp", 1) || !(maxdist > 0.0f))
|
||||
@@ -248,7 +249,7 @@ void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf,
|
||||
const auto distSampleScale = static_cast<float>(device->Frequency) / SpeedOfSoundMetersPerSec;
|
||||
const auto ChanDelay = device->ChannelDelay.as_span();
|
||||
size_t total{0u};
|
||||
for(size_t i{0u};i < conf->Speakers.size();i++)
|
||||
for(size_t i{0u};i < conf->NumSpeakers;i++)
|
||||
{
|
||||
const AmbDecConf::SpeakerConf &speaker = conf->Speakers[i];
|
||||
const ALuint chan{speakermap[i]};
|
||||
@@ -625,18 +626,18 @@ void InitCustomPanning(ALCdevice *device, const bool hqdec, const bool stablize,
|
||||
* front-center channel.
|
||||
*/
|
||||
size_t cidx{0};
|
||||
for(;cidx < conf->Speakers.size();++cidx)
|
||||
for(;cidx < conf->NumSpeakers;++cidx)
|
||||
{
|
||||
if(speakermap[cidx] == FrontCenter)
|
||||
break;
|
||||
}
|
||||
bool hasfc{false};
|
||||
if(cidx < conf->LFMatrix.size())
|
||||
if(cidx < conf->NumSpeakers && conf->FreqBands != 1)
|
||||
{
|
||||
for(const auto &coeff : conf->LFMatrix[cidx])
|
||||
hasfc |= coeff != 0.0f;
|
||||
}
|
||||
if(!hasfc && cidx < conf->HFMatrix.size())
|
||||
if(!hasfc && cidx < conf->NumSpeakers)
|
||||
{
|
||||
for(const auto &coeff : conf->HFMatrix[cidx])
|
||||
hasfc |= coeff != 0.0f;
|
||||
@@ -659,10 +660,10 @@ void InitCustomPanning(ALCdevice *device, const bool hqdec, const bool stablize,
|
||||
|
||||
auto accum_spkr_dist = std::bind(std::plus<float>{}, _1,
|
||||
std::bind(std::mem_fn(&AmbDecConf::SpeakerConf::Distance), _2));
|
||||
const float avg_dist{
|
||||
std::accumulate(conf->Speakers.begin(), conf->Speakers.end(), 0.0f, accum_spkr_dist) /
|
||||
static_cast<float>(conf->Speakers.size())};
|
||||
InitNearFieldCtrl(device, avg_dist, order, !!(conf->ChanMask&AmbiPeriphonicMask));
|
||||
const float accum_dist{std::accumulate(conf->Speakers.get(),
|
||||
conf->Speakers.get()+conf->NumSpeakers, 0.0f, accum_spkr_dist)};
|
||||
InitNearFieldCtrl(device, accum_dist / static_cast<float>(conf->NumSpeakers), order,
|
||||
!!(conf->ChanMask&AmbiPeriphonicMask));
|
||||
|
||||
InitDistanceComp(device, conf, speakermap);
|
||||
}
|
||||
@@ -879,8 +880,8 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, HrtfRequestMode hrtf_appreq
|
||||
{
|
||||
if(!conf.load(decopt->c_str()))
|
||||
ERR("Failed to load layout file %s\n", decopt->c_str());
|
||||
else if(conf.Speakers.size() > MAX_OUTPUT_CHANNELS)
|
||||
ERR("Unsupported speaker count %zu (max %d)\n", conf.Speakers.size(),
|
||||
else if(conf.NumSpeakers > MAX_OUTPUT_CHANNELS)
|
||||
ERR("Unsupported speaker count %zu (max %d)\n", conf.NumSpeakers,
|
||||
MAX_OUTPUT_CHANNELS);
|
||||
else if(conf.ChanMask > Ambi3OrderMask)
|
||||
ERR("Unsupported channel mask 0x%04x (max 0x%x)\n", conf.ChanMask,
|
||||
|
||||
+68
-15
@@ -65,9 +65,11 @@ bool is_at_end(const std::string &buffer, std::size_t endpos)
|
||||
}
|
||||
|
||||
|
||||
bool load_ambdec_speakers(al::vector<AmbDecConf::SpeakerConf> &spkrs, const std::size_t num_speakers, std::istream &f, std::string &buffer)
|
||||
bool load_ambdec_speakers(AmbDecConf::SpeakerConf *spkrs, const std::size_t num_speakers,
|
||||
std::istream &f, std::string &buffer)
|
||||
{
|
||||
while(spkrs.size() < num_speakers)
|
||||
size_t cur_speaker{0};
|
||||
while(cur_speaker < num_speakers)
|
||||
{
|
||||
std::istringstream istr{buffer};
|
||||
|
||||
@@ -84,9 +86,8 @@ bool load_ambdec_speakers(al::vector<AmbDecConf::SpeakerConf> &spkrs, const std:
|
||||
|
||||
if(cmd == "add_spkr")
|
||||
{
|
||||
spkrs.emplace_back();
|
||||
AmbDecConf::SpeakerConf &spkr = spkrs.back();
|
||||
const size_t spkr_num{spkrs.size()};
|
||||
AmbDecConf::SpeakerConf &spkr = spkrs[cur_speaker++];
|
||||
const size_t spkr_num{cur_speaker};
|
||||
|
||||
istr >> spkr.Name;
|
||||
if(istr.fail()) WARN("Name not specified for speaker %zu\n", spkr_num);
|
||||
@@ -118,7 +119,8 @@ bool load_ambdec_speakers(al::vector<AmbDecConf::SpeakerConf> &spkrs, const std:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_ambdec_matrix(float (&gains)[MaxAmbiOrder+1], al::vector<AmbDecConf::CoeffArray> &matrix, const std::size_t maxrow, std::istream &f, std::string &buffer)
|
||||
bool load_ambdec_matrix(float (&gains)[MaxAmbiOrder+1], AmbDecConf::CoeffArray *matrix,
|
||||
const std::size_t maxrow, std::istream &f, std::string &buffer)
|
||||
{
|
||||
bool gotgains{false};
|
||||
std::size_t cur{0u};
|
||||
@@ -159,8 +161,7 @@ bool load_ambdec_matrix(float (&gains)[MaxAmbiOrder+1], al::vector<AmbDecConf::C
|
||||
}
|
||||
else if(cmd == "add_row")
|
||||
{
|
||||
matrix.emplace_back();
|
||||
AmbDecConf::CoeffArray &mtxrow = matrix.back();
|
||||
AmbDecConf::CoeffArray &mtxrow = matrix[cur++];
|
||||
std::size_t curidx{0u};
|
||||
float value{};
|
||||
while(istr.good())
|
||||
@@ -170,15 +171,13 @@ bool load_ambdec_matrix(float (&gains)[MaxAmbiOrder+1], al::vector<AmbDecConf::C
|
||||
if(!istr.eof() && !std::isspace(istr.peek()))
|
||||
{
|
||||
ERR("Extra junk on matrix element %zux%zu: %s\n", curidx,
|
||||
matrix.size(), buffer.c_str()+static_cast<std::size_t>(istr.tellg()));
|
||||
matrix.pop_back();
|
||||
cur, buffer.c_str()+static_cast<std::size_t>(istr.tellg()));
|
||||
return false;
|
||||
}
|
||||
if(curidx < mtxrow.size())
|
||||
mtxrow[curidx++] = value;
|
||||
}
|
||||
std::fill(mtxrow.begin()+curidx, mtxrow.end(), 0.0f);
|
||||
cur++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -216,6 +215,9 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool speakers_loaded{false};
|
||||
bool matrix_loaded{false};
|
||||
bool lfmatrix_loaded{false};
|
||||
std::size_t num_speakers{0u};
|
||||
std::string buffer;
|
||||
while(read_clipped_line(f, buffer))
|
||||
@@ -248,6 +250,11 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
}
|
||||
else if(command == "/dec/chan_mask")
|
||||
{
|
||||
if(ChanMask)
|
||||
{
|
||||
ERR("Duplicate chan_mask\n");
|
||||
return 0;
|
||||
}
|
||||
istr >> std::hex >> ChanMask >> std::dec;
|
||||
if(!istr.eof() && !std::isspace(istr.peek()))
|
||||
{
|
||||
@@ -255,9 +262,19 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
buffer.c_str()+static_cast<std::size_t>(istr.tellg()));
|
||||
return 0;
|
||||
}
|
||||
if(!ChanMask)
|
||||
{
|
||||
ERR("Invalid chan_mask: 0x%08x\n", ChanMask);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if(command == "/dec/freq_bands")
|
||||
{
|
||||
if(FreqBands)
|
||||
{
|
||||
ERR("Duplicate freq_bands\n");
|
||||
return 0;
|
||||
}
|
||||
istr >> FreqBands;
|
||||
if(!istr.eof() && !std::isspace(istr.peek()))
|
||||
{
|
||||
@@ -273,6 +290,11 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
}
|
||||
else if(command == "/dec/speakers")
|
||||
{
|
||||
if(num_speakers)
|
||||
{
|
||||
ERR("Duplicate speakers\n");
|
||||
return 0;
|
||||
}
|
||||
istr >> num_speakers;
|
||||
if(!istr.eof() && !std::isspace(istr.peek()))
|
||||
{
|
||||
@@ -280,9 +302,13 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
buffer.c_str()+static_cast<std::size_t>(istr.tellg()));
|
||||
return 0;
|
||||
}
|
||||
Speakers.reserve(num_speakers);
|
||||
LFMatrix.reserve(num_speakers);
|
||||
HFMatrix.reserve(num_speakers);
|
||||
if(!num_speakers)
|
||||
{
|
||||
ERR("Invalid speakers: %zu\n", num_speakers);
|
||||
return 0;
|
||||
}
|
||||
NumSpeakers = num_speakers;
|
||||
Speakers = std::make_unique<SpeakerConf[]>(num_speakers);
|
||||
}
|
||||
else if(command == "/dec/coeff_scale")
|
||||
{
|
||||
@@ -324,6 +350,11 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
}
|
||||
else if(command == "/speakers/{")
|
||||
{
|
||||
if(!num_speakers)
|
||||
{
|
||||
ERR("AmbDec speakers defined without a count\n");
|
||||
return 0;
|
||||
}
|
||||
const auto endpos = static_cast<std::size_t>(istr.tellg());
|
||||
if(!is_at_end(buffer, endpos))
|
||||
{
|
||||
@@ -332,8 +363,9 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
}
|
||||
buffer.clear();
|
||||
|
||||
if(!load_ambdec_speakers(Speakers, num_speakers, f, buffer))
|
||||
if(!load_ambdec_speakers(Speakers.get(), num_speakers, f, buffer))
|
||||
return 0;
|
||||
speakers_loaded = true;
|
||||
|
||||
if(!read_clipped_line(f, buffer))
|
||||
{
|
||||
@@ -351,6 +383,11 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
}
|
||||
else if(command == "/lfmatrix/{" || command == "/hfmatrix/{" || command == "/matrix/{")
|
||||
{
|
||||
if(!NumSpeakers)
|
||||
{
|
||||
ERR("AmbDec matrix defined without a count\n");
|
||||
return 0;
|
||||
}
|
||||
const auto endpos = static_cast<std::size_t>(istr.tellg());
|
||||
if(!is_at_end(buffer, endpos))
|
||||
{
|
||||
@@ -359,6 +396,13 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
}
|
||||
buffer.clear();
|
||||
|
||||
if(!Matrix)
|
||||
{
|
||||
Matrix = std::make_unique<CoeffArray[]>(NumSpeakers * FreqBands);
|
||||
LFMatrix = Matrix.get();
|
||||
HFMatrix = LFMatrix + NumSpeakers*(FreqBands-1);
|
||||
}
|
||||
|
||||
if(FreqBands == 1)
|
||||
{
|
||||
if(command != "/matrix/{")
|
||||
@@ -368,6 +412,7 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
}
|
||||
if(!load_ambdec_matrix(HFOrderGain, HFMatrix, num_speakers, f, buffer))
|
||||
return 0;
|
||||
matrix_loaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -375,11 +420,13 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
{
|
||||
if(!load_ambdec_matrix(LFOrderGain, LFMatrix, num_speakers, f, buffer))
|
||||
return 0;
|
||||
lfmatrix_loaded = true;
|
||||
}
|
||||
else if(command == "/hfmatrix/{")
|
||||
{
|
||||
if(!load_ambdec_matrix(HFOrderGain, HFMatrix, num_speakers, f, buffer))
|
||||
return 0;
|
||||
matrix_loaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -411,6 +458,12 @@ int AmbDecConf::load(const char *fname) noexcept
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!speakers_loaded || !matrix_loaded || (FreqBands == 2 && !lfmatrix_loaded))
|
||||
{
|
||||
ERR("No decoder defined\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
||||
+7
-4
@@ -2,10 +2,10 @@
|
||||
#define CORE_AMBDEC_H
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "core/ambidefs.h"
|
||||
#include "vector.h"
|
||||
|
||||
/* Helpers to read .ambdec configuration files. */
|
||||
|
||||
@@ -32,15 +32,18 @@ struct AmbDecConf {
|
||||
float Elevation{0.0f};
|
||||
std::string Connection;
|
||||
};
|
||||
al::vector<SpeakerConf> Speakers;
|
||||
size_t NumSpeakers{0};
|
||||
std::unique_ptr<SpeakerConf[]> Speakers;
|
||||
|
||||
using CoeffArray = std::array<float,MaxAmbiChannels>;
|
||||
std::unique_ptr<CoeffArray[]> Matrix;
|
||||
|
||||
/* Unused when FreqBands == 1 */
|
||||
float LFOrderGain[MaxAmbiOrder+1]{};
|
||||
al::vector<CoeffArray> LFMatrix;
|
||||
CoeffArray *LFMatrix;
|
||||
|
||||
float HFOrderGain[MaxAmbiOrder+1]{};
|
||||
al::vector<CoeffArray> HFMatrix;
|
||||
CoeffArray *HFMatrix;
|
||||
|
||||
int load(const char *fname) noexcept;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user