diff options
author | Chris Robinson <[email protected]> | 2017-02-20 09:08:57 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-02-20 09:08:57 -0800 |
commit | 5a2ef2590f38c72883f9ee2e18cc9980634df7be (patch) | |
tree | b26c987fd5bbaa0a4123e45db7232299a2a7e133 | |
parent | b23f81b686f4c72044d0d6f85b5049822f3c6a78 (diff) |
Allow distance compensation for non-HQ rendering as well
It still requires a custom configuration to specify appropriate speaker
distances.
-rw-r--r-- | Alc/panning.c | 81 | ||||
-rw-r--r-- | alsoftrc.sample | 5 | ||||
-rw-r--r-- | utils/alsoft-config/mainwindow.cpp | 9 | ||||
-rw-r--r-- | utils/alsoft-config/mainwindow.h | 2 | ||||
-rw-r--r-- | utils/alsoft-config/mainwindow.ui | 5 |
5 files changed, 49 insertions, 53 deletions
diff --git a/Alc/panning.c b/Alc/panning.c index 00cf9e0b..52618a5e 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -610,6 +610,47 @@ static void InitPanning(ALCdevice *device) } } +static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS]) +{ + const char *devname = al_string_get_cstr(device->DeviceName); + ALfloat maxdist = 0.0f; + ALsizei i; + + for(i = 0;i < conf->NumSpeakers;i++) + maxdist = maxf(maxdist, conf->Speakers[i].Distance); + + if(GetConfigValueBool(devname, "decoder", "distance-comp", 1) && maxdist > 0.0f) + { + ALfloat srate = (ALfloat)device->Frequency; + for(i = 0;i < conf->NumSpeakers;i++) + { + ALsizei chan = speakermap[i]; + ALfloat delay; + + /* 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", + al_string_get_cstr(conf->Speakers[i].Name), 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, + al_string_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length, + device->ChannelDelay[chan].Gain + ); + } + } +} + static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS]) { ChannelMap chanmap[MAX_OUTPUT_CHANNELS]; @@ -688,16 +729,15 @@ static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const A device->FOAOut.Ambi.Coeffs[i][j] = device->Dry.Ambi.Coeffs[i][j] * xyz_scale; } device->FOAOut.CoeffCount = 4; + + InitDistanceComp(device, conf, speakermap); } static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS]) { - const char *devname; size_t count; size_t i; - devname = al_string_get_cstr(device->DeviceName); - if((conf->ChanMask&AMBI_PERIPHONIC_MASK)) { count = (conf->ChanMask > 0x1ff) ? 16 : @@ -756,40 +796,7 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsiz device->FOAOut.CoeffCount = 0; } - ALfloat maxdist = 0.0f; - for(i = 0;i < (size_t)conf->NumSpeakers;i++) - maxdist = maxf(maxdist, conf->Speakers[i].Distance); - - if(GetConfigValueBool(devname, "decoder", "distance-comp", 1) && maxdist > 0.0f) - { - ALfloat srate = (ALfloat)device->Frequency; - for(i = 0;i < (size_t)conf->NumSpeakers;i++) - { - ALsizei chan = speakermap[i]; - ALfloat delay; - - /* 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", - al_string_get_cstr(conf->Speakers[i].Name), 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, - al_string_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length, - device->ChannelDelay[chan].Gain - ); - } - } + InitDistanceComp(device, conf, speakermap); } static void InitHrtfPanning(ALCdevice *device, bool hoa_mode) diff --git a/alsoftrc.sample b/alsoftrc.sample index 256a4d06..36d930bf 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -235,9 +235,8 @@ hq-mode = false # Enables compensation for the speakers' relative distances to the listener. # This applies the necessary delays and attenuation to make the speakers # behave as though they are all equidistant, which is important for proper -# playback of 3D sound rendering. Requires the high-quality ambisonic decoder, -# as well as the proper distances to be specified in the decoder configuration -# file. +# playback of 3D sound rendering. Requires the proper distances to be +# specified in the decoder configuration file. distance-comp = true ## quad: diff --git a/utils/alsoft-config/mainwindow.cpp b/utils/alsoft-config/mainwindow.cpp index ab992843..e4dc10fc 100644 --- a/utils/alsoft-config/mainwindow.cpp +++ b/utils/alsoft-config/mainwindow.cpp @@ -329,7 +329,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->stereoPanningComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(enableApplyButton())); connect(ui->ambiFormatComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(enableApplyButton())); - connect(ui->decoderHQModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(toggleHqState(int))); + connect(ui->decoderHQModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton())); connect(ui->decoderDistCompCheckBox, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton())); connect(ui->decoderQuadLineEdit, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton())); connect(ui->decoderQuadButton, SIGNAL(clicked()), this, SLOT(selectQuadDecoderFile())); @@ -665,7 +665,6 @@ void MainWindow::loadConfig(const QString &fname) ui->decoderHQModeCheckBox->setChecked(hqmode); bool distcomp = settings.value("decoder/distance-comp", true).toBool(); ui->decoderDistCompCheckBox->setChecked(distcomp); - ui->decoderDistCompCheckBox->setEnabled(hqmode); ui->decoderQuadLineEdit->setText(settings.value("decoder/quad").toString()); ui->decoder51LineEdit->setText(settings.value("decoder/surround51").toString()); @@ -1110,12 +1109,6 @@ void MainWindow::updatePeriodCountSlider() } -void MainWindow::toggleHqState(int state) -{ - ui->decoderDistCompCheckBox->setEnabled(state); - enableApplyButton(); -} - void MainWindow::selectQuadDecoderFile() { selectDecoderFile(ui->decoderQuadLineEdit, "Select Quadrophonic Decoder");} void MainWindow::select51DecoderFile() diff --git a/utils/alsoft-config/mainwindow.h b/utils/alsoft-config/mainwindow.h index 6d572df6..8b763845 100644 --- a/utils/alsoft-config/mainwindow.h +++ b/utils/alsoft-config/mainwindow.h @@ -35,8 +35,6 @@ private slots: void updatePeriodCountEdit(int size); void updatePeriodCountSlider(); - void toggleHqState(int state); - void selectQuadDecoderFile(); void select51DecoderFile(); void select61DecoderFile(); diff --git a/utils/alsoft-config/mainwindow.ui b/utils/alsoft-config/mainwindow.ui index f14554e6..afb91996 100644 --- a/utils/alsoft-config/mainwindow.ui +++ b/utils/alsoft-config/mainwindow.ui @@ -601,9 +601,8 @@ appropriate speaker configuration you intend to use.</string> <string>This applies the necessary delays and attenuation to make the speakers behave as though they are all equidistant, which is important for proper -playback of 3D sound rendering. Requires the high -quality ambisonic renderer, as well as the proper -distances to be specified in the decoder +playback of 3D sound rendering. Requires the +proper distances to be specified in the decoder configuration file.</string> </property> <property name="layoutDirection"> |