diff options
author | Chris Robinson <[email protected]> | 2020-12-25 08:31:02 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-12-25 08:31:02 -0800 |
commit | 78f73a42770f436218fc40b85ff804b301201df1 (patch) | |
tree | 341dd48ba1897614676a6190a231534e36a7073e | |
parent | eaf209d2f17e0c5675c1e17fe67d44ac0ef382a0 (diff) |
Avoid dynamic vectors in AmbDecConf
Also add a bit more sanity checking
-rw-r--r-- | alc/bformatdec.cpp | 6 | ||||
-rw-r--r-- | alc/panning.cpp | 29 | ||||
-rw-r--r-- | core/ambdec.cpp | 83 | ||||
-rw-r--r-- | core/ambdec.h | 11 |
4 files changed, 93 insertions, 36 deletions
diff --git a/alc/bformatdec.cpp b/alc/bformatdec.cpp index 0aa65af8..64c45b68 100644 --- a/alc/bformatdec.cpp +++ b/alc/bformatdec.cpp @@ -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; diff --git a/alc/panning.cpp b/alc/panning.cpp index 515dbfcf..8d423d64 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -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, diff --git a/core/ambdec.cpp b/core/ambdec.cpp index a50d6d95..3f390216 100644 --- a/core/ambdec.cpp +++ b/core/ambdec.cpp @@ -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 diff --git a/core/ambdec.h b/core/ambdec.h index 9f0db6b5..6b7394da 100644 --- a/core/ambdec.h +++ b/core/ambdec.h @@ -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; }; |