ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]
:toc: left
:toclevels: 5

= Audio

This module handles audio features.

.VoIP 
* a `voip_server` (nodejs) must be launched for each vRP server (by executing `main.js`)
* nodejs `ws` and `wrtc` packages are required
* the TCP websocket and UDP webrtc range of ports must be opened by firewalls
* see `voip_server/config.js` and `cfg/audio.lua`

TIP: The clients will automatically connect/reconnect themselves to the VoIP server (can be started after, shutdown, restarted).

== Extension

=== Server

[source,lua]
----
self.cfg
self.channels -- map of id => {index, config} (available after the first player connection)

-- register VoIP channel
-- all channels should be registered before any player joins the server
--
-- id: channel name/id (string)
-- config:
--- effects: map of name => true/options
---- spatialization => { max_dist: ..., rolloff: ..., dist_model: ..., ref_dist: ...} (per peer effect)
---- biquad => { frequency: ..., Q: ..., type: ..., detune: ..., gain: ...} see WebAudioAPI BiquadFilter
----- freq = 1700, Q = 3, type = "bandpass" (idea for radio effect)
---- gain => { gain: ... }
Audio:registerVoiceChannel(id, config)
----

=== Client

[source,lua]
----
self.voice_channels = {} -- map of channel => map of player => state (0-1)

-- play audio source (once)
--- url: valid audio HTML url (ex: .ogg/.wav/direct ogg-stream url)
--- volume: 0-1 
--- x,y,z: position (omit for unspatialized)
--- max_dist  (omit for unspatialized)
--- player: (optional) player source id, if passed the spatialized source will be relative to the player (parented)
Audio:playAudioSource(url, volume, x, y, z, max_dist, player)

-- set named audio source (looping)
--- name: source name
--- url: valid audio HTML url (ex: .ogg/.wav/direct ogg-stream url)
--- volume: 0-1 
--- x,y,z: position (omit for unspatialized)
--- max_dist  (omit for unspatialized)
--- player: (optional) player source id, if passed the spatialized source will be relative to the player (parented)
Audio:setAudioSource(name, url, volume, x, y, z, max_dist, player)

-- remove named audio source
Audio:removeAudioSource(name)

-- VoIP

-- create connection to another player for a specific channel
Audio:connectVoice(channel, player)

-- delete connection to another player for a specific channel
-- player: nil to disconnect from all players
Audio:disconnectVoice(channel, player)

-- enable/disable speaking for a specific channel
--- active: true/false 
Audio:setVoiceState(channel, active)

Audio:isSpeaking()

-- TUNNEL

Audio.tunnel.playAudioSource = Audio.playAudioSource
Audio.tunnel.setAudioSource = Audio.setAudioSource
Audio.tunnel.removeAudioSource = Audio.removeAudioSource
Audio.tunnel.connectVoice = Audio.connectVoice
Audio.tunnel.disconnectVoice = Audio.disconnectVoice
Audio.tunnel.setVoiceState = Audio.setVoiceState
----

.Events
[horizontal]
`speakingChange(speaking)`:: called when speaking state changes
`voiceChannelPlayerSpeakingChange(channel, player, speaking)`:: called when the speaking state of a remote player for a specific channel changes (VoIP)
`voiceChannelTransmittingChange(channel, transmitting)`:: called when the transmitting state of the local player for a specific channel changes (VoIP)
