Add a config to output first-, second-, or third-order ambisonics
Currently incomplete, as second- and third-order output will not correctly handle B-Format input buffers. A standalone up-sampler will be needed, similar to the high-quality decoder. Also, output is ACN ordering with SN3D normalization. A config option will eventually be provided to change this if desired.
This commit is contained in:
@@ -1294,6 +1294,9 @@ const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
|
||||
case DevFmtX61: return "6.1 Surround";
|
||||
case DevFmtX71: return "7.1 Surround";
|
||||
case DevFmtBFormat3D: return "B-Format 3D";
|
||||
case DevFmtAmbi1: return "Ambisonics (1st Order)";
|
||||
case DevFmtAmbi2: return "Ambisonics (2nd Order)";
|
||||
case DevFmtAmbi3: return "Ambisonics (3rd Order)";
|
||||
}
|
||||
return "(unknown channels)";
|
||||
}
|
||||
@@ -1325,6 +1328,9 @@ ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
|
||||
case DevFmtX61: return 7;
|
||||
case DevFmtX71: return 8;
|
||||
case DevFmtBFormat3D: return 4;
|
||||
case DevFmtAmbi1: return 4;
|
||||
case DevFmtAmbi2: return 9;
|
||||
case DevFmtAmbi3: return 16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1493,6 +1499,41 @@ void SetDefaultWFXChannelOrder(ALCdevice *device)
|
||||
device->RealOut.ChannelName[2] = Aux2;
|
||||
device->RealOut.ChannelName[3] = Aux3;
|
||||
break;
|
||||
case DevFmtAmbi1:
|
||||
device->RealOut.ChannelName[0] = Aux0;
|
||||
device->RealOut.ChannelName[1] = Aux1;
|
||||
device->RealOut.ChannelName[2] = Aux2;
|
||||
device->RealOut.ChannelName[3] = Aux3;
|
||||
break;
|
||||
case DevFmtAmbi2:
|
||||
device->RealOut.ChannelName[0] = Aux0;
|
||||
device->RealOut.ChannelName[1] = Aux1;
|
||||
device->RealOut.ChannelName[2] = Aux2;
|
||||
device->RealOut.ChannelName[3] = Aux3;
|
||||
device->RealOut.ChannelName[4] = Aux4;
|
||||
device->RealOut.ChannelName[5] = Aux5;
|
||||
device->RealOut.ChannelName[6] = Aux6;
|
||||
device->RealOut.ChannelName[7] = Aux7;
|
||||
device->RealOut.ChannelName[8] = Aux8;
|
||||
break;
|
||||
case DevFmtAmbi3:
|
||||
device->RealOut.ChannelName[0] = Aux0;
|
||||
device->RealOut.ChannelName[1] = Aux1;
|
||||
device->RealOut.ChannelName[2] = Aux2;
|
||||
device->RealOut.ChannelName[3] = Aux3;
|
||||
device->RealOut.ChannelName[4] = Aux4;
|
||||
device->RealOut.ChannelName[5] = Aux5;
|
||||
device->RealOut.ChannelName[6] = Aux6;
|
||||
device->RealOut.ChannelName[7] = Aux7;
|
||||
device->RealOut.ChannelName[8] = Aux8;
|
||||
device->RealOut.ChannelName[9] = Aux9;
|
||||
device->RealOut.ChannelName[10] = Aux10;
|
||||
device->RealOut.ChannelName[11] = Aux11;
|
||||
device->RealOut.ChannelName[12] = Aux12;
|
||||
device->RealOut.ChannelName[13] = Aux13;
|
||||
device->RealOut.ChannelName[14] = Aux14;
|
||||
device->RealOut.ChannelName[15] = Aux15;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1535,6 +1576,9 @@ void SetDefaultChannelOrder(ALCdevice *device)
|
||||
case DevFmtX51:
|
||||
case DevFmtX61:
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
break;
|
||||
}
|
||||
@@ -1992,10 +2036,12 @@ 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->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2)
|
||||
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]);
|
||||
else if(device->FmtChans == DevFmtAmbi2 || device->FmtChans == DevFmtAmbi3)
|
||||
size += 4 * sizeof(device->Dry.Buffer[0]);
|
||||
device->Dry.Buffer = al_calloc(16, size);
|
||||
if(!device->Dry.Buffer)
|
||||
{
|
||||
@@ -2014,10 +2060,11 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
device->RealOut.NumChannels = device->Dry.NumChannels;
|
||||
}
|
||||
|
||||
if(device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2)
|
||||
if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) ||
|
||||
device->FmtChans == DevFmtAmbi2 || device->FmtChans == DevFmtAmbi3)
|
||||
{
|
||||
/* Higher-order high quality decoding requires upsampling first-order
|
||||
* content, so make sure to mix it separately.
|
||||
/* Higher-order rendering 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;
|
||||
@@ -3409,6 +3456,9 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
|
||||
{ "surround61", DevFmtX61 },
|
||||
{ "surround71", DevFmtX71 },
|
||||
{ "surround51rear", DevFmtX51Rear },
|
||||
{ "ambisonic1", DevFmtAmbi1 },
|
||||
{ "ambisonic2", DevFmtAmbi2 },
|
||||
{ "ambisonic3", DevFmtAmbi3 },
|
||||
};
|
||||
size_t i;
|
||||
|
||||
|
||||
@@ -529,6 +529,9 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
case DevFmtX61:
|
||||
case DevFmtX71:
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -473,6 +473,9 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
|
||||
OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
|
||||
break;
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
device->FmtChans = DevFmtStereo;
|
||||
/*fall-through*/
|
||||
case DevFmtStereo:
|
||||
@@ -789,6 +792,9 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
|
||||
SPEAKER_SIDE_RIGHT;
|
||||
break;
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -882,6 +882,9 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
|
||||
OutputType.dwChannelMask = MONO;
|
||||
break;
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
device->FmtChans = DevFmtStereo;
|
||||
/*fall-through*/
|
||||
case DevFmtStereo:
|
||||
@@ -1523,6 +1526,9 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self)
|
||||
break;
|
||||
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
return E_FAIL;
|
||||
}
|
||||
switch(device->FmtType)
|
||||
|
||||
@@ -79,7 +79,11 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans)
|
||||
SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
|
||||
SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
|
||||
SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
|
||||
case DevFmtBFormat3D: break;
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -999,6 +999,9 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
|
||||
mapname = "mono";
|
||||
break;
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
device->FmtChans = DevFmtStereo;
|
||||
/*fall-through*/
|
||||
case DevFmtStereo:
|
||||
|
||||
@@ -277,6 +277,11 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
|
||||
case DevFmtX51Rear: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020; break;
|
||||
case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break;
|
||||
case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break;
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
device->FmtChans = DevFmtBFormat3D;
|
||||
/*fall-through*/
|
||||
case DevFmtBFormat3D:
|
||||
isbformat = 1;
|
||||
chanmask = 0;
|
||||
|
||||
@@ -562,6 +562,9 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name)
|
||||
case DevFmtX61:
|
||||
case DevFmtX71:
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
return ALC_INVALID_ENUM;
|
||||
}
|
||||
|
||||
|
||||
@@ -961,7 +961,9 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device
|
||||
props->Reverb.LateReverbPan, gain,
|
||||
props->Reverb.ReflectionsGain,
|
||||
props->Reverb.LateReverbGain, State);
|
||||
else if(Device->FmtChans == DevFmtBFormat3D || Device->AmbiDecoder)
|
||||
else if(Device->FmtChans == DevFmtBFormat3D || Device->FmtChans == DevFmtAmbi1 ||
|
||||
Device->FmtChans == DevFmtAmbi2 || Device->FmtChans == DevFmtAmbi3 ||
|
||||
Device->AmbiDecoder)
|
||||
Update3DPanning(Device, props->Reverb.ReflectionsPan,
|
||||
props->Reverb.LateReverbPan, gain,
|
||||
props->Reverb.ReflectionsGain,
|
||||
|
||||
+41
-1
@@ -575,6 +575,9 @@ static void InitPanning(ALCdevice *device)
|
||||
break;
|
||||
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -593,6 +596,40 @@ static void InitPanning(ALCdevice *device)
|
||||
device->FOAOut.Ambi = device->Dry.Ambi;
|
||||
device->FOAOut.CoeffCount = device->Dry.CoeffCount;
|
||||
}
|
||||
else if(device->FmtChans == DevFmtAmbi1)
|
||||
{
|
||||
count = 4;
|
||||
for(i = 0;i < count;i++)
|
||||
{
|
||||
device->Dry.Ambi.Map[i].Scale = 1.0f/SN3D2N3DScale[i];
|
||||
device->Dry.Ambi.Map[i].Index = i;
|
||||
}
|
||||
device->Dry.CoeffCount = 0;
|
||||
device->Dry.NumChannels = count;
|
||||
|
||||
device->FOAOut.Ambi = device->Dry.Ambi;
|
||||
device->FOAOut.CoeffCount = device->Dry.CoeffCount;
|
||||
}
|
||||
else if(device->FmtChans == DevFmtAmbi2 || device->FmtChans == DevFmtAmbi3)
|
||||
{
|
||||
count = (device->FmtChans == DevFmtAmbi3) ? 16 :
|
||||
(device->FmtChans == DevFmtAmbi2) ? 9 : 1;
|
||||
for(i = 0;i < count;i++)
|
||||
{
|
||||
device->Dry.Ambi.Map[i].Scale = 1.0f/SN3D2N3DScale[i];
|
||||
device->Dry.Ambi.Map[i].Index = i;
|
||||
}
|
||||
device->Dry.CoeffCount = 0;
|
||||
device->Dry.NumChannels = count;
|
||||
|
||||
memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi));
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
device->FOAOut.Ambi.Map[i].Scale = 1.0f;
|
||||
device->FOAOut.Ambi.Map[i].Index = i;
|
||||
}
|
||||
device->FOAOut.CoeffCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetChannelMap(device->RealOut.ChannelName, device->Dry.Ambi.Coeffs,
|
||||
@@ -835,10 +872,13 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
|
||||
case DevFmtX51Rear: layout = "surround51rear"; break;
|
||||
case DevFmtX61: layout = "surround61"; break;
|
||||
case DevFmtX71: layout = "surround71"; break;
|
||||
/* Mono, Stereo, and B-Fornat output don't use custom decoders. */
|
||||
/* Mono, Stereo, and Ambisonics output don't use custom decoders. */
|
||||
case DevFmtMono:
|
||||
case DevFmtStereo:
|
||||
case DevFmtBFormat3D:
|
||||
case DevFmtAmbi1:
|
||||
case DevFmtAmbi2:
|
||||
case DevFmtAmbi3:
|
||||
break;
|
||||
}
|
||||
if(layout)
|
||||
|
||||
@@ -448,6 +448,9 @@ enum DevFmtChannels {
|
||||
DevFmtX51Rear = 0x80000000,
|
||||
|
||||
DevFmtBFormat3D,
|
||||
DevFmtAmbi1,
|
||||
DevFmtAmbi2,
|
||||
DevFmtAmbi3,
|
||||
|
||||
DevFmtChannelsDefault = DevFmtStereo
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user