Engage Audio Devices - rallytac/pub GitHub Wiki
Engage Audio Devices
Audio devices (microphones & speakers) in Engage used for audio capture and playout come in two flavors - (a) hardware-based devices provided by the OS platform and (b), application-defined audio devices (ADADs) which are managed entirely by the application using the Engage Engine. Both types of devices reside in the Engage Engine in the form of a registry which tracks unique identifiers for the various input and output devices.
During initialization, the Engage Engine queries the OS interfaces for audio hardware, building the registry as it goes. Subsequent to that, the application may register its own devices to add to that master registry. Once the registry is complete, groups (channels) are created - each potentially with their own input and output numeric identifiers for audio. These numeric identifiers are assigned automatically when the registry is built and/or ADADs are registered by the application.
Overriding Automatic Registry Creation
Now, sometimes, you may want to specifically include or exclude particular OS-provided hardware devices - forcing Engage to only use the registry you provide instead of what is reported by the platform. This may be done in the Engine's policy JSON used during initialization.
Below is an example where we've told Engage to operate at an 8Khz sampling rate in mono (i.e. not stereo) mode (the internalRate
and internalChannels
) settings.
What we've also done is provided a registry for Engage to use - overriding its normal procedure of hardware discovery. This is done in the registry
object.
.
.
"audio": {
"internalRate": 8000,
"internalChannels": 1,
"allowOutputOnTransmit": false,
"muteTxOnTx": true,
"registry": {
"inputs": [
{
"hardwareId": "default",
"isDefault": true,
"name": "The default microphone"
},
{
"hardwareId": "engage_audio_in_port01",
"name": "A virtual microphone defined for Engage"
}
],
"outputs": [
{
"hardwareId": "default",
"isDefault": true,
"name": "The default speaker"
},
{
"hardwareId": "engage_audio_out_port01",
"isDefault": false,
"name": "A virtual speaker defined for Engage"
}
]
}
}
.
.
In the example - which is tailored for Linux using ALSA - we've defined a registry with two inputs and two outputs. The first input has a hardware ID of default
and is marked as the default with the isDefault
setting. We've also defined a second input named engage_audio_in_port01
. This is a virtual recording device which (again this is for Linux) which we've defined in the ALSA configuration as follows:
pcm.engage_audio_in_port01 {
type plug
slave.pcm "hw:0,0"
}
Similarly, we've done the same for our outputs - with a default
and a engage_audio_out_port01
virtual device.
In fact, our ALSA configuration looks as follows:
# Engage Audio Input Ports
pcm.engage_audio_in_port01 {
type plug
slave.pcm "hw:0,0"
}
pcm.engage_audio_in_port02 {
type plug
slave.pcm "hw:0,0"
}
# Engage Audio Output Ports
pcm.engage_audio_out_port01 {
type plug
slave.pcm "hw:0,0"
}
pcm.engage_audio_out_port02 {
type plug
slave.pcm "hw:0,0"
}
Notice how the
slave.pcm
value is the same for all devices as the Linux machine only has one physical hardware audio card. This value would obviously be different on your machine where you may have multiple audio hardware cards.
Using Device Names Instead Of IDs
OK, cool; we've managed to (narrowly!) define Engage's audio device registry, using the audio.registry
subobject in the Engage policy. But what is the numeric ID !? It hasn't (and cannot) be defined in our JSON-based registry. And therefore we cannot specify a group's audio.inputId
or audio.outputId
numeric values. Wouldn't it be nice if we could just use the names we defined in our registry?
Good news - we can!
Instead of using audio.inputId
and/or audio.outputId
, we'll use audio.inputHardwareId
and audio.outputHardwareId
as shown below. When the AirSupport
group is created in Engage, it will use the name provided - say engage_audio_in_port01
to search the registry for the device that has a hardware ID of engage_audio_in_port01
to determine the numeric ID which will then be used automagically in the configuration.
{
"id": "c0fda052-e0a0-47ec-88ab-e34a61ce5b1a",
"name": "My Mission Name",
"description": "Just a little mission to play with",
"groups": [
{
"id": "AirSupport",
"type": 1,
"name": "AirSupport",
"audio": {
"inputHardwareId": "engage_audio_in_port01",
"outputHardwareId": "engage_audio_out_port01"
},
"txAudio": {
"encoder": 25
},
"tx": {
"address": "234.5.6.7",
"port": 17000
},
"rx": {
"address": "234.5.6.7",
"port": 17000
}
}
]
}
In a Linux environment - as we've seen - that name is defined in the ALSA configuration, and that's all that Engage needs to use that device.
Easy huh!?