From 7bdd68ddbe896bc7d50a8a43ba093d66e1c0216e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 9 Apr 2016 08:04:56 -0700 Subject: Use frequency-dependent processing for the ambisonic up-sampler --- Alc/bformatdec.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'Alc') diff --git a/Alc/bformatdec.c b/Alc/bformatdec.c index e4c6da49..dd0561d0 100644 --- a/Alc/bformatdec.c +++ b/Alc/bformatdec.c @@ -114,6 +114,12 @@ static const ALfloat SquareMatrixHF[4][MAX_AMBI_COEFFS] = { { 0.353553f, 0.204094f, 0.0f, -0.204094f }, { 0.353553f, -0.204094f, 0.0f, -0.204094f }, }; +static const ALfloat SquareMatrixLF[4][MAX_AMBI_COEFFS] = { + { 0.25f, 0.204094f, 0.0f, 0.204094f }, + { 0.25f, -0.204094f, 0.0f, 0.204094f }, + { 0.25f, 0.204094f, 0.0f, -0.204094f }, + { 0.25f, -0.204094f, 0.0f, -0.204094f }, +}; static ALfloat SquareEncoder[4][MAX_AMBI_COEFFS]; static const ALfloat CubeMatrixHF[8][MAX_AMBI_COEFFS] = { @@ -126,6 +132,16 @@ static const ALfloat CubeMatrixHF[8][MAX_AMBI_COEFFS] = { { 0.25f, 0.14425f, -0.14425f, -0.14425f }, { 0.25f, -0.14425f, -0.14425f, -0.14425f }, }; +static const ALfloat CubeMatrixLF[8][MAX_AMBI_COEFFS] = { + { 0.125f, 0.125f, 0.125f, 0.125f }, + { 0.125f, -0.125f, 0.125f, 0.125f }, + { 0.125f, 0.125f, 0.125f, -0.125f }, + { 0.125f, -0.125f, 0.125f, -0.125f }, + { 0.125f, 0.125f, -0.125f, 0.125f }, + { 0.125f, -0.125f, -0.125f, 0.125f }, + { 0.125f, 0.125f, -0.125f, -0.125f }, + { 0.125f, -0.125f, -0.125f, -0.125f }, +}; static ALfloat CubeEncoder[8][MAX_AMBI_COEFFS]; static alonce_flag encoder_inited = AL_ONCE_FLAG_INIT; @@ -188,7 +204,10 @@ typedef struct BFormatDec { } Delay[MAX_OUTPUT_CHANNELS]; struct { + BandSplitter XOver[4]; + const ALfloat (*restrict MatrixHF)[MAX_AMBI_COEFFS]; + const ALfloat (*restrict MatrixLF)[MAX_AMBI_COEFFS]; const ALfloat (*restrict Encoder)[MAX_AMBI_COEFFS]; ALuint NumChannels; } UpSampler; @@ -251,8 +270,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, dec->SamplesLF = NULL; dec->NumChannels = chancount; - dec->Samples = al_calloc(16, dec->NumChannels * conf->FreqBands * - sizeof(dec->Samples[0])); + dec->Samples = al_calloc(16, dec->NumChannels*2 * sizeof(dec->Samples[0])); dec->SamplesHF = dec->Samples; dec->SamplesLF = dec->SamplesHF + dec->NumChannels; @@ -266,9 +284,13 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, else if(conf->CoeffScale == ADS_FuMa) coeff_scale = FuMa2N3DScale; + ratio = 400.0f / (ALfloat)srate; + for(i = 0;i < 4;i++) + bandsplit_init(&dec->UpSampler.XOver[i], ratio); if((conf->ChanMask & ~0x831b)) { dec->UpSampler.MatrixHF = CubeMatrixHF; + dec->UpSampler.MatrixLF = CubeMatrixLF; dec->UpSampler.Encoder = (const ALfloat(*)[MAX_AMBI_COEFFS])CubeEncoder; dec->UpSampler.NumChannels = 8; dec->Periphonic = AL_TRUE; @@ -276,6 +298,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, else { dec->UpSampler.MatrixHF = SquareMatrixHF; + dec->UpSampler.MatrixLF = SquareMatrixLF; dec->UpSampler.Encoder = (const ALfloat(*)[MAX_AMBI_COEFFS])SquareEncoder; dec->UpSampler.NumChannels = 4; dec->Periphonic = AL_FALSE; @@ -510,6 +533,15 @@ void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[B { ALuint i, j, k; + /* First, split the first-order components into low and high frequency + * bands. This assumes SamplesHF and SamplesLF have enough space for first- + * order content (to which, this up-sampler is only used with second-order + * or higher decoding, so it will). + */ + for(i = 0;i < InChannels;i++) + bandsplit_process(&dec->UpSampler.XOver[i], dec->SamplesHF[i], dec->SamplesLF[i], + InSamples[i], SamplesToDo); + /* This up-sampler is very simplistic. It essentially decodes the first- * order content to a square channel array (or cube if height is desired), * then encodes those points onto the higher order soundfield. @@ -517,7 +549,9 @@ void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[B for(k = 0;k < dec->UpSampler.NumChannels;k++) { memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat)); - apply_row(dec->ChannelMix, dec->UpSampler.MatrixHF[k], InSamples, + apply_row(dec->ChannelMix, dec->UpSampler.MatrixHF[k], dec->SamplesHF, + InChannels, SamplesToDo); + apply_row(dec->ChannelMix, dec->UpSampler.MatrixLF[k], dec->SamplesLF, InChannels, SamplesToDo); for(j = 0;j < dec->NumChannels;j++) -- cgit v1.2.3