diff options
author | Chris Robinson <[email protected]> | 2016-07-30 09:29:21 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-07-30 09:29:21 -0700 |
commit | 33a84f17ac78ac1f77b48fbd1193fafab5ca14e7 (patch) | |
tree | 66055c0a89d22552b856038434333b2ca2eb06cc /Alc/bformatdec.c | |
parent | b5b3ea95f899410a5392fb633ace74c10bbd9921 (diff) |
Add a stand-alone upsampler for higher-order ambisonic oputput
Diffstat (limited to 'Alc/bformatdec.c')
-rw-r--r-- | Alc/bformatdec.c | 85 |
1 files changed, 77 insertions, 8 deletions
diff --git a/Alc/bformatdec.c b/Alc/bformatdec.c index d6cf25e2..3c175b33 100644 --- a/Alc/bformatdec.c +++ b/Alc/bformatdec.c @@ -130,6 +130,16 @@ static const ALfloat SquareMatrix[4][FB_Max][MAX_AMBI_COEFFS] = { }; static ALfloat SquareEncoder[4][MAX_AMBI_COEFFS]; +static const ALfloat CubePoints[8][3] = { + { -0.577350269f, 0.577350269f, -0.577350269f }, + { 0.577350269f, 0.577350269f, -0.577350269f }, + { -0.577350269f, 0.577350269f, 0.577350269f }, + { 0.577350269f, 0.577350269f, 0.577350269f }, + { -0.577350269f, -0.577350269f, -0.577350269f }, + { 0.577350269f, -0.577350269f, -0.577350269f }, + { -0.577350269f, -0.577350269f, 0.577350269f }, + { 0.577350269f, -0.577350269f, 0.577350269f }, +}; static const ALfloat CubeMatrix[8][FB_Max][MAX_AMBI_COEFFS] = { { { 0.25f, 0.14425f, 0.14425f, 0.14425f }, { 0.125f, 0.125f, 0.125f, 0.125f } }, { { 0.25f, -0.14425f, 0.14425f, 0.14425f }, { 0.125f, -0.125f, 0.125f, 0.125f } }, @@ -167,14 +177,8 @@ static void init_bformatdec(void) MixMatrixRow = SelectMixer(); - CalcXYZCoeffs(-0.577350269f, 0.577350269f, -0.577350269f, 0.0f, CubeEncoder[0]); - CalcXYZCoeffs( 0.577350269f, 0.577350269f, -0.577350269f, 0.0f, CubeEncoder[1]); - CalcXYZCoeffs(-0.577350269f, 0.577350269f, 0.577350269f, 0.0f, CubeEncoder[2]); - CalcXYZCoeffs( 0.577350269f, 0.577350269f, 0.577350269f, 0.0f, CubeEncoder[3]); - CalcXYZCoeffs(-0.577350269f, -0.577350269f, -0.577350269f, 0.0f, CubeEncoder[4]); - CalcXYZCoeffs( 0.577350269f, -0.577350269f, -0.577350269f, 0.0f, CubeEncoder[5]); - CalcXYZCoeffs(-0.577350269f, -0.577350269f, 0.577350269f, 0.0f, CubeEncoder[6]); - CalcXYZCoeffs( 0.577350269f, -0.577350269f, 0.577350269f, 0.0f, CubeEncoder[7]); + for(i = 0;i < COUNTOF(CubePoints);i++) + CalcDirectionCoeffs(CubePoints[i], 0.0f, CubeEncoder[i]); CalcXYZCoeffs(-0.707106781f, 0.0f, -0.707106781f, 0.0f, SquareEncoder[0]); CalcXYZCoeffs( 0.707106781f, 0.0f, -0.707106781f, 0.0f, SquareEncoder[1]); @@ -588,3 +592,68 @@ void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[B } } } + + +typedef struct AmbiUpsampler { + alignas(16) ALfloat SamplesHF[4][BUFFERSIZE]; + alignas(16) ALfloat SamplesLF[4][BUFFERSIZE]; + + alignas(16) ALfloat ChannelMix[BUFFERSIZE]; + + BandSplitter XOver[4]; + + ALfloat Gains[8][MAX_OUTPUT_CHANNELS]; + ALuint NumChannels; +} AmbiUpsampler; + +AmbiUpsampler *ambiup_alloc() +{ + alcall_once(&bformatdec_inited, init_bformatdec); + return al_calloc(16, sizeof(AmbiUpsampler)); +} + +void ambiup_free(struct AmbiUpsampler *ambiup) +{ + al_free(ambiup); +} + +void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device) +{ + ALfloat ratio; + ALuint i; + + ratio = 400.0f / (ALfloat)device->Frequency; + for(i = 0;i < 4;i++) + bandsplit_init(&ambiup->XOver[i], ratio); + + ambiup->NumChannels = COUNTOF(CubePoints); + for(i = 0;i < ambiup->NumChannels;i++) + ComputePanningGains(device->Dry, CubeEncoder[i], 1.0f, ambiup->Gains[i]); +} + +void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo) +{ + ALuint i, j, k; + + for(i = 0;i < 4;i++) + bandsplit_process(&ambiup->XOver[i], ambiup->SamplesHF[i], ambiup->SamplesLF[i], + InSamples[i], SamplesToDo); + + for(k = 0;k < ambiup->NumChannels;k++) + { + memset(ambiup->ChannelMix, 0, SamplesToDo*sizeof(ALfloat)); + MixMatrixRow(ambiup->ChannelMix, CubeMatrix[k][FB_HighFreq], + ambiup->SamplesHF, 4, SamplesToDo); + MixMatrixRow(ambiup->ChannelMix, CubeMatrix[k][FB_LowFreq], + ambiup->SamplesLF, 4, SamplesToDo); + + for(j = 0;j < OutChannels;j++) + { + ALfloat gain = ambiup->Gains[k][j]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + for(i = 0;i < SamplesToDo;i++) + OutBuffer[j][i] += ambiup->ChannelMix[i] * gain; + } + } +} |