Clean up a few more loops

This commit is contained in:
Chris Robinson
2018-12-10 14:49:57 -08:00
parent d91ada2e02
commit ed18fd76c5
2 changed files with 95 additions and 83 deletions
+82 -81
View File
@@ -136,13 +136,10 @@ void SetChannelMap(const Channel (&devchans)[MAX_OUTPUT_CHANNELS], ChannelConfig
*outcount = mini(maxcount, MAX_OUTPUT_CHANNELS);
}
bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei speakermap[MAX_OUTPUT_CHANNELS])
bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei (&speakermap)[MAX_OUTPUT_CHANNELS])
{
for(ALsizei i{0};i < conf->NumSpeakers;i++)
auto map_spkr = [device](const AmbDecConf::SpeakerConf &speaker) -> ALsizei
{
enum Channel ch;
int chidx = -1;
/* NOTE: AmbDec does not define any standard speaker names, however
* for this to work we have to by able to find the output channel
* the speaker definition corresponds to. Therefore, OpenAL Soft
@@ -163,67 +160,67 @@ bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei speakerma
* use the side channels when the device is configured for back,
* and vice-versa.
*/
if(conf->Speakers[i].Name == "LF")
Channel ch{};
if(speaker.Name == "LF")
ch = FrontLeft;
else if(conf->Speakers[i].Name == "RF")
else if(speaker.Name == "RF")
ch = FrontRight;
else if(conf->Speakers[i].Name == "CE")
else if(speaker.Name == "CE")
ch = FrontCenter;
else if(conf->Speakers[i].Name == "LS")
else if(speaker.Name == "LS")
{
if(device->FmtChans == DevFmtX51Rear)
ch = BackLeft;
else
ch = SideLeft;
}
else if(conf->Speakers[i].Name == "RS")
else if(speaker.Name == "RS")
{
if(device->FmtChans == DevFmtX51Rear)
ch = BackRight;
else
ch = SideRight;
}
else if(conf->Speakers[i].Name == "LB")
else if(speaker.Name == "LB")
{
if(device->FmtChans == DevFmtX51)
ch = SideLeft;
else
ch = BackLeft;
}
else if(conf->Speakers[i].Name == "RB")
else if(speaker.Name == "RB")
{
if(device->FmtChans == DevFmtX51)
ch = SideRight;
else
ch = BackRight;
}
else if(conf->Speakers[i].Name == "CB")
else if(speaker.Name == "CB")
ch = BackCenter;
else
{
const char *name = conf->Speakers[i].Name.c_str();
const char *name{speaker.Name.c_str()};
unsigned int n;
char c;
if(sscanf(name, "AUX%u%c", &n, &c) == 1 && n < 16)
ch = static_cast<enum Channel>(Aux0+n);
ch = static_cast<Channel>(Aux0+n);
else
{
ERR("AmbDec speaker label \"%s\" not recognized\n", name);
return false;
return -1;
}
}
chidx = GetChannelIdxByName(&device->RealOut, ch);
const int chidx{GetChannelIdxByName(&device->RealOut, ch)};
if(chidx == -1)
{
ERR("Failed to lookup AmbDec speaker label %s\n",
conf->Speakers[i].Name.c_str());
return false;
}
speakermap[i] = chidx;
}
return true;
ERR("Failed to lookup AmbDec speaker label %s\n", speaker.Name.c_str());
return chidx;
};
auto speakers_end = std::begin(conf->Speakers) + conf->NumSpeakers;
std::transform(std::begin(conf->Speakers), speakers_end, std::begin(speakermap), map_spkr);
/* Return success if no invalid entries are found. */
auto speakermap_end = std::begin(speakermap) + conf->NumSpeakers;
return std::find(std::begin(speakermap), speakermap_end, -1) == speakermap_end;
}
@@ -264,79 +261,83 @@ constexpr ChannelMap MonoCfg[1] = {
void InitNearFieldCtrl(ALCdevice *device, ALfloat ctrl_dist, ALsizei order, const ALsizei *RESTRICT chans_per_order)
{
const char *devname = device->DeviceName.c_str();
ALsizei i;
/* NFC is only used when AvgSpeakerDist is greater than 0, and can only be
* used when rendering to an ambisonic buffer.
*/
const char *devname{device->DeviceName.c_str()};
if(!GetConfigValueBool(devname, "decoder", "nfc", 1) || !(ctrl_dist > 0.0f))
return;
if(GetConfigValueBool(devname, "decoder", "nfc", 1) && ctrl_dist > 0.0f)
{
/* NFC is only used when AvgSpeakerDist is greater than 0, and can only
* be used when rendering to an ambisonic buffer.
*/
device->AvgSpeakerDist = minf(ctrl_dist, 10.0f);
TRACE("Using near-field reference distance: %.2f meters\n", device->AvgSpeakerDist);
device->AvgSpeakerDist = minf(ctrl_dist, 10.0f);
TRACE("Using near-field reference distance: %.2f meters\n", device->AvgSpeakerDist);
for(i = 0;i < order+1;i++)
device->NumChannelsPerOrder[i] = chans_per_order[i];
for(;i < MAX_AMBI_ORDER+1;i++)
device->NumChannelsPerOrder[i] = 0;
}
auto iter = std::copy(chans_per_order, chans_per_order+order+1,
std::begin(device->NumChannelsPerOrder));
std::fill(iter, std::end(device->NumChannelsPerOrder), 0);
}
void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const ALsizei (&speakermap)[MAX_OUTPUT_CHANNELS])
{
const char *devname = device->DeviceName.c_str();
ALfloat maxdist = 0.0f;
size_t total = 0;
ALsizei i;
using namespace std::placeholders;
for(i = 0;i < conf->NumSpeakers;i++)
maxdist = maxf(maxdist, conf->Speakers[i].Distance);
auto speakers_end = std::begin(conf->Speakers) + conf->NumSpeakers;
const ALfloat maxdist{
std::accumulate(std::begin(conf->Speakers), speakers_end, float{0.0f},
std::bind(maxf, _1, std::bind(std::mem_fn(&AmbDecConf::SpeakerConf::Distance), _2))
)
};
if(GetConfigValueBool(devname, "decoder", "distance-comp", 1) && maxdist > 0.0f)
const char *devname{device->DeviceName.c_str()};
if(!GetConfigValueBool(devname, "decoder", "distance-comp", 1) || !(maxdist > 0.0f))
return;
auto srate = static_cast<ALfloat>(device->Frequency);
size_t total{0u};
for(ALsizei i{0};i < conf->NumSpeakers;i++)
{
ALfloat srate = (ALfloat)device->Frequency;
for(i = 0;i < conf->NumSpeakers;i++)
{
ALsizei chan = speakermap[i];
ALfloat delay;
const AmbDecConf::SpeakerConf &speaker = conf->Speakers[i];
const ALsizei chan{speakermap[i]};
/* Distance compensation only delays in steps of the sample rate.
* This is a bit less accurate since the delay time falls to the
* nearest sample time, but it's far simpler as it doesn't have to
* deal with phase offsets. This means at 48khz, for instance, the
* distance delay will be in steps of about 7 millimeters.
*/
delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC *
srate + 0.5f);
if(delay >= (ALfloat)MAX_DELAY_LENGTH)
ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
conf->Speakers[i].Name.c_str(), delay, MAX_DELAY_LENGTH);
/* Distance compensation only delays in steps of the sample rate. This
* is a bit less accurate since the delay time falls to the nearest
* sample time, but it's far simpler as it doesn't have to deal with
* phase offsets. This means at 48khz, for instance, the distance delay
* will be in steps of about 7 millimeters.
*/
const ALfloat delay{
std::floor((maxdist - speaker.Distance)/SPEEDOFSOUNDMETRESPERSEC*srate + 0.5f)
};
if(delay >= (ALfloat)MAX_DELAY_LENGTH)
ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %d)\n",
speaker.Name.c_str(), delay, MAX_DELAY_LENGTH);
device->ChannelDelay[chan].Length = (ALsizei)clampf(
delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1)
);
device->ChannelDelay[chan].Gain = conf->Speakers[i].Distance / maxdist;
TRACE("Channel %u \"%s\" distance compensation: %d samples, %f gain\n", chan,
conf->Speakers[i].Name.c_str(), device->ChannelDelay[chan].Length,
device->ChannelDelay[chan].Gain
);
device->ChannelDelay[chan].Length = static_cast<ALsizei>(clampf(
delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1)
));
device->ChannelDelay[chan].Gain = speaker.Distance / maxdist;
TRACE("Channel %u \"%s\" distance compensation: %d samples, %f gain\n", chan,
speaker.Name.c_str(), device->ChannelDelay[chan].Length,
device->ChannelDelay[chan].Gain
);
/* Round up to the next 4th sample, so each channel buffer starts
* 16-byte aligned.
*/
total += RoundUp(device->ChannelDelay[chan].Length, 4);
}
/* Round up to the next 4th sample, so each channel buffer starts
* 16-byte aligned.
*/
total += RoundUp(device->ChannelDelay[chan].Length, 4);
}
if(total > 0)
{
device->ChannelDelay.resize(total);
device->ChannelDelay[0].Buffer = device->ChannelDelay.data();
for(i = 1;i < MAX_OUTPUT_CHANNELS;i++)
auto set_bufptr = [](const DistanceComp::DistData &last, const DistanceComp::DistData &cur) -> DistanceComp::DistData
{
size_t len = RoundUp(device->ChannelDelay[i-1].Length, 4);
device->ChannelDelay[i].Buffer = device->ChannelDelay[i-1].Buffer + len;
}
DistanceComp::DistData ret{cur};
ret.Buffer = last.Buffer + RoundUp(last.Length, 4);
return ret;
};
std::partial_sum(device->ChannelDelay.begin(), device->ChannelDelay.end(),
device->ChannelDelay.begin(), set_bufptr);
}
}
+13 -2
View File
@@ -608,15 +608,19 @@ typedef struct EnumeratedHrtf {
#define MAX_DELAY_LENGTH 1024
class DistanceComp {
public:
struct DistData {
ALfloat Gain{1.0f};
ALsizei Length{0}; /* Valid range is [0...MAX_DELAY_LENGTH). */
ALfloat *Buffer{nullptr};
} mChannel[MAX_OUTPUT_CHANNELS];
};
private:
DistData mChannel[MAX_OUTPUT_CHANNELS];
al::vector<ALfloat,16> mSamples;
public:
void resize(size_t amt) { mSamples.resize(amt); }
void resize(size_t new_size) { mSamples.resize(new_size); }
void shrink_to_fit() { mSamples.shrink_to_fit(); }
void clear() noexcept
{
@@ -629,6 +633,13 @@ public:
mSamples.clear();
}
DistData *begin() noexcept { return std::begin(mChannel); }
const DistData *begin() const noexcept { return std::begin(mChannel); }
const DistData *cbegin() const noexcept { return std::begin(mChannel); }
DistData *end() noexcept { return std::end(mChannel); }
const DistData *end() const noexcept { return std::end(mChannel); }
const DistData *cend() const noexcept { return std::end(mChannel); }
ALfloat *data() noexcept { return mSamples.data(); }
const ALfloat *data() const noexcept { return mSamples.data(); }