195 lines
8.0 KiB
Python
195 lines
8.0 KiB
Python
|
|
import boto3 # pip install boto3
|
|
import pygame # pip install pygame
|
|
import time
|
|
import io
|
|
import random
|
|
import os
|
|
|
|
# -------------------------------------------------------------------
|
|
# Enter your access data and your AWS region
|
|
# -------------------------------------------------------------------
|
|
atc_aws_key = "YOUR_AWS_KEY"
|
|
atc_aws_secret = "YOUR_AWS_SECRET"
|
|
atc_aws_region = "SERVER REGION"
|
|
# -------------------------------------------------------------------
|
|
|
|
# -------------------------------------------------------------------
|
|
# Do you want to see ATC messages in the console also?
|
|
# -------------------------------------------------------------------
|
|
atc_show_responses = True
|
|
|
|
# -------------------------------------------------------------------
|
|
# The voice model you want to use.
|
|
#
|
|
# IMPORTANT:
|
|
# Depending on the model you want, the prices are per 1m characters
|
|
# generated vary *drastically*.
|
|
# 'standard' is the cheapest, 'neural' the most expensive one.
|
|
# Depending on the model you pick, the list of voices vary also.
|
|
#
|
|
# Pricing: https://aws.amazon.com/polly/pricing/
|
|
# -------------------------------------------------------------------
|
|
atc_aws_voicemodel = 'standard'
|
|
# atc_aws_voicemodel = 'neural'
|
|
|
|
|
|
# -------------------------------------------------------------------
|
|
# Define where your X-Plane log file is located
|
|
# This usually sits in the root of your X-Plane folder, named Log.txt
|
|
# -------------------------------------------------------------------
|
|
atc_xplane_log = "M:\\Flight Sim\\Simulator\\12\\Log_tmp.txt"
|
|
#atc_xplane_log = "C:\\Users\\windo\\Desktop\\Log.txt"
|
|
|
|
# -------------------------------------------------------------------
|
|
# Put in your call sign. Must be the same you entered in 124th ATC
|
|
# -------------------------------------------------------------------
|
|
atc_callsign = "MST"
|
|
atc_flightno = "6012"
|
|
|
|
|
|
# -------------------------------------------------------------------
|
|
# Do you want to hear "your voice" when contacting ATC?
|
|
# -------------------------------------------------------------------
|
|
atc_captain_voice = True
|
|
|
|
# -------------------------------------------------------------------
|
|
# Select your pilot's voice
|
|
# Ideally you will need to remove your selected voice from the array
|
|
# of available Polly voices below, so that it does not come up as
|
|
# your ATC voice
|
|
# -------------------------------------------------------------------
|
|
atc_pilot_voice = 12
|
|
|
|
|
|
# -------------------------------------------------------------------
|
|
# NO TRESPASSING BEYOND THIS POINT
|
|
# -------------------------------------------------------------------
|
|
|
|
os.system("cls")
|
|
print(" ")
|
|
print(" ---------------------------------------------- ")
|
|
print(" 124thAWS")
|
|
print(" Making 124thATC sound more natural")
|
|
print(" ---------------------------------------------- ")
|
|
print(" Developed by MarStrMind")
|
|
print(" License: MIT")
|
|
print(" ---------------------------------------------- ")
|
|
print(" Using file: " + atc_xplane_log)
|
|
print(" ---------------------------------------------- ")
|
|
print(" ")
|
|
|
|
# The voice names available for playback, depending on the model
|
|
# Of course, you can remove any that you do not like
|
|
# Sources for voice names:
|
|
# - https://docs.aws.amazon.com/polly/latest/dg/neural-voices.html
|
|
# - https://docs.aws.amazon.com/polly/latest/dg/standard-voices.html
|
|
atc_voices = None
|
|
if atc_aws_voicemodel == "standard":
|
|
atc_voices = ["Nicole", "Russell", "Amy", "Emma", "Brian", "Aditi", "Raveena", "Joanna", "Kendra", "Kimberly", "Salli", "Joey", "Geraint"]
|
|
# After testing, I removed Ivy from this list. It sounded too child-like.
|
|
if atc_aws_voicemodel == "neural":
|
|
atc_voices = ["Olivia", "Amy", "Emma", "Brian", "Arthur", "Kajal", "Niamh", "Aria", "Ayanda", "Danielle", "Gregory", "Ivy", "Joanna", "Kendra", "Kimberly", "Salli", "Joey", "Matthew", "Ruth", "Stephen"]
|
|
# Missing in this list are Justin and Kevin -
|
|
# they are declared as being young child voices - you normally do not hear children on an ATC transmission.
|
|
|
|
|
|
# Setup our Polly session to AWS
|
|
atc_polly_client = boto3.Session(
|
|
aws_access_key_id=atc_aws_key,
|
|
aws_secret_access_key=atc_aws_secret,
|
|
region_name=atc_aws_region).client('polly')
|
|
|
|
# Last read line
|
|
atc_last_line = -1
|
|
|
|
# Init pygame and its mixer
|
|
pygame.init()
|
|
pygame.mixer.init()
|
|
|
|
# Open file before main loop
|
|
atc_log = open(atc_xplane_log)
|
|
|
|
# Who spoke last - pilot or ATC
|
|
atc_wsl = 1 # 1: pilot, 2: ATC. Initially set to 1
|
|
|
|
# Main run loop
|
|
while True:
|
|
atc_lines = atc_log.readlines()
|
|
idx = 0
|
|
for line in atc_lines:
|
|
if "Communication:" in line:
|
|
content = line.split()
|
|
c_idx = 0
|
|
for word in content:
|
|
if word == "Communication:":
|
|
break
|
|
c_idx = c_idx + 1
|
|
|
|
new_l_el = 0
|
|
newline = ""
|
|
for word in content:
|
|
if new_l_el >= c_idx+1:
|
|
newline = newline + " " + word
|
|
new_l_el = new_l_el + 1
|
|
|
|
if idx > atc_last_line:
|
|
# Update last read line
|
|
atc_last_line = idx
|
|
|
|
# Pick a voice - depending on current situation
|
|
resp = ""
|
|
voice_to_use = -1
|
|
content[c_idx+2] = content[c_idx+2].replace(",", "")
|
|
if content[c_idx+1] == atc_callsign and content[c_idx+2] == atc_flightno:
|
|
vc = random.randrange(len(atc_voices))
|
|
if vc == atc_pilot_voice:
|
|
vc = vc-1
|
|
if vc == -1:
|
|
vc = 1
|
|
voice_to_use = vc
|
|
resp = "ATC"
|
|
atc_wsl = 2
|
|
else:
|
|
voice_to_use = atc_pilot_voice
|
|
resp = "Pilot"
|
|
atc_wsl = 1
|
|
|
|
# Show what has been said so that it can be verified outside of Pilot2ATC - if the user wants it
|
|
if atc_show_responses == True:
|
|
print(" > " + resp + " - [" + atc_voices[voice_to_use] + "]: " + newline)
|
|
|
|
# Let's replace the actual numbers with written, phonetic numbers to avoid things like
|
|
# "6012" audible as "six thousand twelve". Note the space after each number.
|
|
# We need to do this after the string checks performed before.
|
|
# Placing this here shows original text in console - but pronounces the numbers correctly.
|
|
newline = newline.replace("0", "Zero ")
|
|
newline = newline.replace("1", "One ")
|
|
newline = newline.replace("2", "Two ")
|
|
newline = newline.replace("3", "Three ")
|
|
newline = newline.replace("4", "Four ")
|
|
newline = newline.replace("5", "Five ")
|
|
newline = newline.replace("6", "Six ")
|
|
newline = newline.replace("7", "Seven ")
|
|
newline = newline.replace("8", "Eight ")
|
|
newline = newline.replace("9", "Niner ")
|
|
|
|
# Generate voice!
|
|
# Let's keep it at OGG - best compromize between data transfer size and quality
|
|
response = atc_polly_client.synthesize_speech(VoiceId=atc_voices[voice_to_use], OutputFormat='ogg_vorbis', Text = newline, Engine = atc_aws_voicemodel)
|
|
# And place that into a binary block
|
|
data = io.BytesIO(response['AudioStream'].read())
|
|
|
|
# Place the data into pygame and play it
|
|
pygame.mixer.music.load(data)
|
|
if resp == "ATC":
|
|
pygame.mixer.music.play()
|
|
if resp == "Pilot" and atc_captain_voice == True:
|
|
pygame.mixer.music.play()
|
|
pygame.event.wait()
|
|
|
|
# Increase loop count
|
|
idx = idx + 1
|
|
|
|
atc_log.seek(0)
|
|
time.sleep(3) |