* Initial SRS addition
This commit is contained in:
Applevangelist 2023-06-16 18:18:18 +02:00
parent bfe7bf1af5
commit c80213b4cf
3 changed files with 283 additions and 104 deletions

View File

@ -152,6 +152,7 @@
-- @field #boolean ICLSon Automatic ICLS is activated.
-- @field #number ICLSchannel ICLS channel.
-- @field #string ICLSmorse ICLS morse code, e.g. "STN".
-- @field #AIRBOSS.Radio PilotRadio Radio for Pilot calls.
-- @field #AIRBOSS.Radio LSORadio Radio for LSO calls.
-- @field #number LSOFreq LSO radio frequency in MHz.
-- @field #string LSOModu LSO radio modulation "AM" or "FM".
@ -1731,6 +1732,10 @@ AIRBOSS.Difficulty = {
-- @field #table trapsheet Groove data table recorded every 0.5 seconds.
-- @field #boolean trapon If true, save trap sheets.
-- @field #string debriefschedulerID Debrief scheduler ID.
--
-- @field Sound.SRS#MSRS SRS
-- @field Sound.SRS#MSRSQUEUE SRSQ
--
-- @extends #AIRBOSS.FlightGroup
--- Main group level radio menu: F10 Other/Airboss.
@ -1743,7 +1748,7 @@ AIRBOSS.MenuF10Root = nil
--- Airboss class version.
-- @field #string version
AIRBOSS.version = "1.3.0"
AIRBOSS.version = "1.3.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -3043,12 +3048,56 @@ function AIRBOSS:SetBeaconRefresh( TimeInterval )
return self
end
--- Set up SRS for usage without sound files
-- @param #AIRBOSS self
-- @param #string PathToSRS Path to SRS folder, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone".
-- @param #number Port Port of the SRS server, defaults to 5002.
-- @param #string Culture (Optional) Culture, defaults to "en-US".
-- @param #string Gender (Optional) Gender, e.g. "male" or "female". Defaults to "male".
-- @param #string Voice (Optional) Set to use a specific voice. Will **override gender and culture** settings.
-- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json".
-- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest).
-- @param #table AltBackend (Optional) See MSRS for details.
-- @return #AIRBOSS self
function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volume,AltBackend)
-- SRS
local Frequency = self.MarshalRadio.frequency
local Modulation = self.MarshalRadio.modulation
self.SRS = MSRS:New(PathToSRS,Frequency,Modulation,Volume,AltBackend)
self.SRS:SetCoalition(self:GetCoalition())
self.SRS:SetCoordinate(self:GetCoordinate())
self.SRS:SetCulture(Culture or "en-US")
--self.SRS:SetFrequencies(Frequencies)
self.SRS:SetGender(Gender or "male")
self.SRS:SetPath(PathToSRS)
self.SRS:SetPort(Port or 5002)
self.SRS:SetLabel(self.MarshalRadio.alias or "AIRBOSS")
--self.SRS:SetModulations(Modulations)
if GoogleCreds then
self.SRS:SetGoogle(GoogleCreds)
end
if Voice then
self.SRS:SetVoice(Voice)
end
self.SRS:SetVolume(Volume or 1.0)
-- SRSQUEUE
self.SRSQ = MSRSQUEUE:New("AIRBOSS")
self.SRSQ:SetTransmitOnlyWithPlayers(true)
if not self.PilotRadio then
self:SetSRSPilotVoice()
end
return self
end
--- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM.
-- @param #AIRBOSS self
-- @param #number Frequency (Optional) Frequency in MHz. Default 264 MHz.
-- @param #string Modulation (Optional) Modulation, "AM" or "FM". Default "AM".
-- @param #string Voice (Optional) SRS specific voice
-- @param #string Gender (Optional) SRS specific gender
-- @param #string Culture (Optional) SRS specific culture
-- @return #AIRBOSS self
function AIRBOSS:SetLSORadio( Frequency, Modulation )
function AIRBOSS:SetLSORadio( Frequency, Modulation, Voice, Gender, Culture )
self.LSOFreq = (Frequency or 264)
Modulation = Modulation or "AM"
@ -3063,6 +3112,9 @@ function AIRBOSS:SetLSORadio( Frequency, Modulation )
self.LSORadio.frequency = self.LSOFreq
self.LSORadio.modulation = self.LSOModu
self.LSORadio.alias = "LSO"
self.LSORadio.voice = Voice
self.LSORadio.gender = Gender or "male"
self.LSORadio.culture = Culture or "en-US"
return self
end
@ -3071,8 +3123,11 @@ end
-- @param #AIRBOSS self
-- @param #number Frequency (Optional) Frequency in MHz. Default 305 MHz.
-- @param #string Modulation (Optional) Modulation, "AM" or "FM". Default "AM".
-- @param #string Voice (Optional) SRS specific voice
-- @param #string Gender (Optional) SRS specific gender
-- @param #string Culture (Optional) SRS specific culture
-- @return #AIRBOSS self
function AIRBOSS:SetMarshalRadio( Frequency, Modulation )
function AIRBOSS:SetMarshalRadio( Frequency, Modulation, Voice, Gender, Culture )
self.MarshalFreq = Frequency or 305
Modulation = Modulation or "AM"
@ -3087,6 +3142,9 @@ function AIRBOSS:SetMarshalRadio( Frequency, Modulation )
self.MarshalRadio.frequency = self.MarshalFreq
self.MarshalRadio.modulation = self.MarshalModu
self.MarshalRadio.alias = "MARSHAL"
self.MarshalRadio.voice = Voice
self.MarshalRadio.gender = Gender or "male"
self.MarshalRadio.culture = Culture or "en-US"
return self
end
@ -14588,59 +14646,129 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
if radio == nil or call == nil then
return
end
-- Create a new radio transmission item.
local transmission = {} -- #AIRBOSS.Radioitem
transmission.radio = radio
transmission.call = call
transmission.Tplay = timer.getAbsTime() + (delay or 0)
transmission.interval = interval
transmission.isplaying = false
transmission.Tstarted = nil
transmission.loud = loud and call.loud
-- Player onboard number if sender has one.
if self:_IsOnboard( call.modexsender ) then
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
end
-- Play onboard number if receiver has one.
if self:_IsOnboard( call.modexreceiver ) then
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
end
-- Add transmission to the right queue.
local caller = ""
if radio.alias == "LSO" then
table.insert( self.RQLSO, transmission )
caller = "LSOCall"
-- Schedule radio queue checks.
if not self.RQLid then
self:T( self.lid .. string.format( "Starting LSO radio queue." ) )
self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 )
if not self.SRS then
-- Create a new radio transmission item.
local transmission = {} -- #AIRBOSS.Radioitem
transmission.radio = radio
transmission.call = call
transmission.Tplay = timer.getAbsTime() + (delay or 0)
transmission.interval = interval
transmission.isplaying = false
transmission.Tstarted = nil
transmission.loud = loud and call.loud
-- Player onboard number if sender has one.
if self:_IsOnboard( call.modexsender ) then
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
end
elseif radio.alias == "MARSHAL" then
table.insert( self.RQMarshal, transmission )
caller = "MarshalCall"
if not self.RQMid then
self:T( self.lid .. string.format( "Starting Marhal radio queue." ) )
self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 )
-- Play onboard number if receiver has one.
if self:_IsOnboard( call.modexreceiver ) then
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
end
-- Add transmission to the right queue.
local caller = ""
if radio.alias == "LSO" then
table.insert( self.RQLSO, transmission )
caller = "LSOCall"
-- Schedule radio queue checks.
if not self.RQLid then
self:T( self.lid .. string.format( "Starting LSO radio queue." ) )
self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 )
end
elseif radio.alias == "MARSHAL" then
table.insert( self.RQMarshal, transmission )
caller = "MarshalCall"
if not self.RQMid then
self:T( self.lid .. string.format( "Starting Marhal radio queue." ) )
self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 )
end
end
-- Append radio click sound at the end of the transmission.
if click then
self:RadioTransmission( radio, self[caller].CLICK, false, delay )
end
else
-- SRS transmission
local frequency = self.MarshalRadio.frequency
local modulation = self.MarshalRadio.modulation
local voice = nil
local gender = nil
local culture = nil
if radio.alias == "MARSHAL" or radio.alias == "AIRBOSS" then
voice = self.MarshalRadio.voice
gender = self.MarshalRadio.gender
culture = self.MarshalRadio.culture
end
if radio.alias == "LSO" then
frequency = self.LSORadio.frequency
modulation = self.LSORadio.modulation
voice = self.LSORadio.voice
gender = self.LSORadio.gender
culture = self.LSORadio.culture
end
if pilotcall then
voice = self.PilotRadio.voice
gender = self.PilotRadio.gender
culture = self.PilotRadio.culture
radio.alias = "PILOT"
end
if not radio.alias then
-- TODO - what freq to use here?
frequency = 243
modulation = radio.modulation.AM
radio.alias = "AIRBOSS"
end
local volume = nil
if loud then
volume = 1.0
end
--local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle
local text = call.subtitle
self:I(text)
local srstext = string.gsub(text,"\n","; ")
self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, tstart, 0.1, subgroups, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias)
end
end
-- Append radio click sound at the end of the transmission.
if click then
self:RadioTransmission( radio, self[caller].CLICK, false, delay )
--- Set SRS voice for the pilot calls.
-- @param #AIRBOSS self
-- @param #string Voice (Optional) SRS specific voice
-- @param #string Gender (Optional) SRS specific gender
-- @param #string Culture (Optional) SRS specific culture
-- @return #AIRBOSS self
function AIRBOSS:SetSRSPilotVoice( Voice, Gender, Culture )
self.PilotRadio = {} -- #AIRBOSS.Radio
self.PilotRadio.alias = "PILOT"
self.PilotRadio.voice = Voice or MSRS.Voices.Microsoft.David
self.PilotRadio.gender = Gender or "male"
self.PilotRadio.culture = Culture or "en-US"
if (not Voice) and self.SRS and self.SRS.google then
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
end
return self
end
--- Check if a call needs a subtitle because the complete voice overs are not available.
@ -14920,49 +15048,81 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
-- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear )
else
-- Wait until previous sound finished.
local wait = 0
-- Onboard number to get the attention.
if receiver == playerData.onboard then
-- Which voice over number to use.
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
-- User sound of board number.
wait = wait + self:_Number2Sound( playerData, sender, receiver )
if not self.SRS then
-- Wait until previous sound finished.
local wait = 0
-- Onboard number to get the attention.
if receiver == playerData.onboard then
-- Which voice over number to use.
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
-- User sound of board number.
wait = wait + self:_Number2Sound( playerData, sender, receiver )
end
end
-- Negative.
if string.find( text:lower(), "negative" ) then
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.NEGATIVE.duration
end
-- Affirm.
if string.find( text:lower(), "affirm" ) then
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.AFFIRMATIVE.duration
end
-- Roger.
if string.find( text:lower(), "roger" ) then
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.ROGER.duration
end
-- Play click sound to end message.
if wait > 0 then
local filename = self:_RadioFilename( self.MarshalCall.CLICK )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
end
else
-- SRS transmission
local frequency = self.MarshalRadio.frequency
local modulation = self.MarshalRadio.modulation
local voice = nil
local gender = nil
local culture = nil
if sender == "MARSHAL" or sender == "AIRBOSS" then
voice = self.MarshalRadio.voice
gender = self.MarshalRadio.gender
culture = self.MarshalRadio.culture
end
if sender == "LSO" then
frequency = self.LSORadio.frequency
modulation = self.LSORadio.modulation
voice = self.LSORadio.voice
gender = self.LSORadio.gender
culture = self.LSORadio.culture
elseif not sender then
-- TODO - what freq to use here?
frequency = 243
modulation = radio.modulation.AM
sender = "AIRBOSS"
end
-- local text = tostring(receiver or "").."; "..sender.."; "..text
--local text = sender.."; "..text
self:I(text)
local srstext = string.gsub(text,"\n","; ")
self.SRSQ:NewTransmission(srstext,duration,self.SRS,tstart,0.1,subgroups,subtitle,subduration,frequency,modulation,gender,culture,voice,volume,sender)
end
-- Negative.
if string.find( text:lower(), "negative" ) then
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.NEGATIVE.duration
end
-- Affirm.
if string.find( text:lower(), "affirm" ) then
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.AFFIRMATIVE.duration
end
-- Roger.
if string.find( text:lower(), "roger" ) then
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.ROGER.duration
end
-- Play click sound to end message.
if wait > 0 then
local filename = self:_RadioFilename( self.MarshalCall.CLICK )
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
end
-- Text message to player client.
if playerData.client then
MESSAGE:New( text, duration, sender, clear ):ToClient( playerData.client )
@ -16301,7 +16461,7 @@ function AIRBOSS:_RequestSpinning( _unitName )
-- Some advice.
if playerData.difficulty == AIRBOSS.Difficulty.EASY then
local text = "Climb to 1200 feet and proceed to the initial again."
self:MessageToPlayer( playerData, text, "INSTRUCTOR", "" )
self:MessageToPlayer( playerData, text, "AIRBOSS", "" )
end
return

View File

@ -1347,6 +1347,11 @@ MSRSQUEUE = {
-- @field #number interval Interval in seconds before next transmission.
-- @field #boolean TransmitOnlyWithPlayers If true, only transmit if there are alive Players.
-- @field Core.Set#SET_CLIENT PlayerSet PlayerSet created when TransmitOnlyWithPlayers == true
-- @field #string gender Voice gender
-- @field #string culture Voice culture
-- @field #string voice Voice if any
-- @field #number volume Volume
-- @field #string label Label to be used
--- Create a new MSRSQUEUE object for a given radio frequency/modulation.
-- @param #MSRSQUEUE self
@ -1426,8 +1431,13 @@ end
-- @param #number subduration Duration [sec] of the subtitle being displayed. Default 5 sec.
-- @param #number frequency Radio frequency if other than MSRS default.
-- @param #number modulation Radio modulation if other then MSRS default.
-- @param #string gender Gender of the voice
-- @param #string culture Culture of the voice
-- @param #string voice Specific voice
-- @param #number volume Volume setting
-- @param #string label Label to be used
-- @return #MSRSQUEUE.Transmission Radio transmission table.
function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation)
function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation, gender, culture, voice, volume, label)
if self.TransmitOnlyWithPlayers then
if self.PlayerSet and self.PlayerSet:CountAlive() == 0 then
@ -1462,6 +1472,11 @@ function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgr
else
transmission.subduration=0 --nil
end
transmission.gender = gender
transmission.culture = culture
transmission.voice = voice
transmission.gender = volume
transmission.label = label
-- Add transmission to queue.
self:AddTransmission(transmission)
@ -1475,7 +1490,7 @@ end
function MSRSQUEUE:Broadcast(transmission)
if transmission.frequency then
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, Gender, Culture, Voice, Volume, Label)
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label)
else
transmission.msrs:PlayText(transmission.text)
end

View File

@ -35,6 +35,7 @@ do
-- @field #number id
-- @field #number side
-- @field #number slot
-- @field #numner timestamp
--- Encapsules multiplayer environment scripting functions from [net](https://wiki.hoggitworld.com/view/DCS_singleton_net)
-- with some added FSM functions and options to block/unblock players in MP environments.
@ -205,7 +206,7 @@ function NET:_EventHandler(EventData)
-- Joining
if data.id == EVENTS.PlayerEnterUnit or data.id == EVENTS.PlayerEnterAircraft then
self:T(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid)
self:T(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid.." | Event ID: "..data.id)
-- Check for blockages
local blocked = self:IsAnyBlocked(ucid,name,PlayerID,PlayerSide,PlayerSlot)
@ -213,15 +214,18 @@ function NET:_EventHandler(EventData)
-- block pilot
local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' )
else
self.KnownPilots[name] = {
name = name,
ucid = ucid,
id = PlayerID,
side = PlayerSide,
slot = PlayerSlot,
}
local client = CLIENT:FindByPlayerName(name) or data.IniUnit
self:__PlayerJoined(1,client,name)
if not self.KnownPilots[name] or (self.KnownPilots[name] and TNow-self.KnownPilots[name].timestamp > 3) then
self:__PlayerJoined(1,client,name)
self.KnownPilots[name] = {
name = name,
ucid = ucid,
id = PlayerID,
side = PlayerSide,
slot = PlayerSlot,
timestamp = TNow,
}
end
return self
end
end