diff options
-rw-r--r-- | Alc/ALc.c | 20 | ||||
-rw-r--r-- | Alc/ALu.c | 4 | ||||
-rw-r--r-- | Alc/bformatdec.c | 8 | ||||
-rw-r--r-- | Alc/bformatdec.h | 1 | ||||
-rw-r--r-- | Alc/effects/compressor.c | 5 | ||||
-rw-r--r-- | Alc/effects/equalizer.c | 5 | ||||
-rw-r--r-- | Alc/effects/modulator.c | 5 | ||||
-rw-r--r-- | Alc/panning.c | 10 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 9 |
9 files changed, 62 insertions, 5 deletions
@@ -2133,7 +2133,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) /* Allocate extra channels for any post-filter output. */ size = device->Dry.NumChannels * sizeof(device->Dry.Buffer[0]); - if(device->Hrtf || device->Uhj_Encoder || device->AmbiDecoder) + if(device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) + size += (ChannelsFromDevFmt(device->FmtChans)+4) * sizeof(device->Dry.Buffer[0]); + else if(device->Hrtf || device->Uhj_Encoder || device->AmbiDecoder) size += ChannelsFromDevFmt(device->FmtChans) * sizeof(device->Dry.Buffer[0]); device->Dry.Buffer = al_calloc(16, size); if(!device->Dry.Buffer) @@ -2157,6 +2159,22 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->RealOut.NumChannels = device->Dry.NumChannels; } + if(device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) + { + /* Higher-order high quality decoding requires upsampling first-order + * content, so make sure to mix it separately. + */ + device->FOAOut.Buffer = device->RealOut.Buffer + device->RealOut.NumChannels; + device->FOAOut.NumChannels = 4; + } + else + { + device->FOAOut.Buffer = device->Dry.Buffer; + device->FOAOut.NumChannels = device->Dry.NumChannels; + memcpy(device->FOAOut.AmbiCoeffs, device->Dry.AmbiCoeffs, + sizeof(device->FOAOut.AmbiCoeffs)); + } + SetMixerFPUMode(&oldMode); V0(device->Backend,lock)(); context = ATOMIC_LOAD(&device->ContextList); @@ -513,8 +513,10 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A 0.0f, -V[0]*scale, V[1]*scale, -V[2]*scale ); + voice->Direct.OutBuffer = Device->FOAOut.Buffer; + voice->Direct.OutChannels = Device->FOAOut.NumChannels; for(c = 0;c < num_channels;c++) - ComputeFirstOrderGains(Device->Dry.AmbiCoeffs, Device->Dry.NumChannels, matrix.m[c], + ComputeFirstOrderGains(Device->FOAOut.AmbiCoeffs, Device->FOAOut.NumChannels, matrix.m[c], DryGain, voice->Direct.Gains[c].Target); /* Rebuild the matrix, without the second- or third-order output diff --git a/Alc/bformatdec.c b/Alc/bformatdec.c index f5a8e8c4..37be67e4 100644 --- a/Alc/bformatdec.c +++ b/Alc/bformatdec.c @@ -142,6 +142,14 @@ void bformatdec_free(BFormatDec *dec) } } +int bformatdec_getOrder(const struct BFormatDec *dec) +{ + if(dec->NumChannels > 9) return 3; + if(dec->NumChannels > 4) return 2; + if(dec->NumChannels > 1) return 1; + return 0; +} + void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS]) { const ALfloat *coeff_scale = UnitScale; diff --git a/Alc/bformatdec.h b/Alc/bformatdec.h index a322f41d..5f17d711 100644 --- a/Alc/bformatdec.h +++ b/Alc/bformatdec.h @@ -8,6 +8,7 @@ struct BFormatDec; struct BFormatDec *bformatdec_alloc(); void bformatdec_free(struct BFormatDec *dec); +int bformatdec_getOrder(const struct BFormatDec *dec); void bformatdec_reset(struct BFormatDec *dec, const struct AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS]); void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo); diff --git a/Alc/effects/compressor.c b/Alc/effects/compressor.c index ae859793..6358f672 100644 --- a/Alc/effects/compressor.c +++ b/Alc/effects/compressor.c @@ -70,8 +70,11 @@ static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice 0.0f, 0.0f, scale, 0.0f, 0.0f, 0.0f, 0.0f, scale ); + + STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer; + STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels; for(i = 0;i < 4;i++) - ComputeFirstOrderGains(device->Dry.AmbiCoeffs, device->Dry.NumChannels, + ComputeFirstOrderGains(device->FOAOut.AmbiCoeffs, device->FOAOut.NumChannels, matrix.m[i], slot->Gain, state->Gain[i]); } diff --git a/Alc/effects/equalizer.c b/Alc/effects/equalizer.c index 479a8536..ffc9830f 100644 --- a/Alc/effects/equalizer.c +++ b/Alc/effects/equalizer.c @@ -110,8 +110,11 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice * 0.0f, 0.0f, gain, 0.0f, 0.0f, 0.0f, 0.0f, gain ); + + STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer; + STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels; for(i = 0;i < MAX_EFFECT_CHANNELS;i++) - ComputeFirstOrderGains(device->Dry.AmbiCoeffs, device->Dry.NumChannels, + ComputeFirstOrderGains(device->FOAOut.AmbiCoeffs, device->FOAOut.NumChannels, matrix.m[i], slot->Gain, state->Gain[i]); /* Calculate coefficients for the each type of filter. Note that the shelf diff --git a/Alc/effects/modulator.c b/Alc/effects/modulator.c index 4183b908..c283d4b0 100644 --- a/Alc/effects/modulator.c +++ b/Alc/effects/modulator.c @@ -129,8 +129,11 @@ static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCdevice * 0.0f, 0.0f, scale, 0.0f, 0.0f, 0.0f, 0.0f, scale ); + + STATIC_CAST(ALeffectState,state)->OutBuffer = Device->FOAOut.Buffer; + STATIC_CAST(ALeffectState,state)->OutChannels = Device->FOAOut.NumChannels; for(i = 0;i < MAX_EFFECT_CHANNELS;i++) - ComputeFirstOrderGains(Device->Dry.AmbiCoeffs, Device->Dry.NumChannels, + ComputeFirstOrderGains(Device->FOAOut.AmbiCoeffs, Device->FOAOut.NumChannels, matrix.m[i], Slot->Gain, state->Gain[i]); } diff --git a/Alc/panning.c b/Alc/panning.c index 16c84b6d..401d29d6 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -646,6 +646,16 @@ ALvoid aluInitPanning(ALCdevice *device) TRACE("Enabling %s-band ambisonic decoder\n", (conf.FreqBands==1)?"single":"dual"); bformatdec_reset(device->AmbiDecoder, &conf, count, device->Frequency, speakermap); ambdec_deinit(&conf); + + if(bformatdec_getOrder(device->AmbiDecoder) >= 2) + { + memset(device->FOAOut.AmbiCoeffs, 0, sizeof(device->FOAOut.AmbiCoeffs)); + device->FOAOut.AmbiCoeffs[0][0] = 1.0f; + device->FOAOut.AmbiCoeffs[1][1] = 1.0f; + device->FOAOut.AmbiCoeffs[2][2] = 1.0f; + device->FOAOut.AmbiCoeffs[3][3] = 1.0f; + } + return; ambi_fail: diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index c71e844f..b870059b 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -507,6 +507,15 @@ struct ALCdevice_struct ALuint NumChannels; } Dry; + /* First-order ambisonics output, to be upsampled to the dry buffer if different. */ + struct { + /* Ambisonic coefficients for mixing. */ + ChannelConfig AmbiCoeffs[MAX_OUTPUT_CHANNELS]; + + ALfloat (*Buffer)[BUFFERSIZE]; + ALuint NumChannels; + } FOAOut; + /* Virtual output, to be post-processed to the real output. */ struct { ALfloat (*Buffer)[BUFFERSIZE]; |