Skip to content

Commit

Permalink
1. working on multitasking.
Browse files Browse the repository at this point in the history
2. working on intonations.
3. some general refactoring.
  • Loading branch information
DoubleCouponDay committed Apr 17, 2017
1 parent 405772f commit 0e6d6d5
Show file tree
Hide file tree
Showing 23 changed files with 436 additions and 368 deletions.
29 changes: 14 additions & 15 deletions ChatManager.cs → ChatEntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@
namespace SETextToSpeechMod
{
[MySessionComponentDescriptor (MyUpdateOrder.BeforeSimulation)] //adds an attribute tag telling the game to run my script.
public class ChatManager : MySessionComponentBase
public class ChatEntryPoint : MySessionComponentBase
{
const ushort packet_ID = 60452; //the convention is to use the last 4-5 digits of your steam mod as packet ID

bool initialised;
private bool debugging = false;

private Task asyncCallAllowed;
private readonly bool debugging;

private Encoding encode = Encoding.Unicode; //encoding is necessary to convert message into correct format.
private SoundPlayer soundPlayer;
public OutputManager OutputManager { get; private set; }

public ChatManager(){}
public ChatEntryPoint(){}

public ChatManager (bool isDebugging)
public ChatEntryPoint (bool isDebugging)
{
debugging = isDebugging;
}
Expand All @@ -33,13 +32,7 @@ public override void UpdateBeforeSimulation()
{
Initialise();
}

if (asyncCallAllowed == null ||
(asyncCallAllowed?.IsCompleted != null && //Apprently && operator will not continue evaluating if its previous evaluation was false
asyncCallAllowed?.IsCompleted == true))
{
asyncCallAllowed = OutputManager.RunAsync();
}
OutputManager.Run();
}

public void Initialise() //this wouldnt work as a constructor because im guessing some assets arent available during load time.
Expand Down Expand Up @@ -155,7 +148,12 @@ public void OnReceivedPacket (byte[] receivedPacket) //action type method which
}
}

//dont blame me if your string gets cut the fuck up if it doesnt contain a signature!
/// <summary>
/// Gets the serialized header within a transmission packet.
/// Dont blame me if your string is destroyed when it doesn't contain a signature!
/// </summary>
/// <param name="packet"></param>
/// <returns></returns>
private string ExtractSignatureFromPacket (ref string packet)
{
char[] dividedMessage = packet.ToCharArray();
Expand All @@ -175,7 +173,8 @@ protected override void UnloadData() //will run when the session closes to preve
{
initialised = false;
MyAPIGateway.Utilities.MessageEntered -= OnMessageEntered;
MyAPIGateway.Multiplayer.UnregisterMessageHandler (packet_ID, OnReceivedPacket);
MyAPIGateway.Multiplayer.UnregisterMessageHandler (packet_ID, OnReceivedPacket);
OutputManager.DisposeOfUnsafe();
}
}

Expand Down
2 changes: 1 addition & 1 deletion LookUpTables/PrettyScaryDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static class PrettyScaryDictionary
{"_I_", ROW}, {"IM", new string[]{ EYE, MIH, }}, {"ILL", new string[]{ EYE, LIH, "", }}, {"INFINIT", new string[]{ IHH, NIH, FIH, IHH, NIH, IHH, TIH, }}, {"INTEREST", new string[]{ IHH, NIH, TIH, ERR, " ", EHH, SIH, TIH, }},
{"_J_", ROW}, {"JENKINS", new string[]{JIH, EHH, NIH, KIH, IHH, NIH, SIH}},
{"_K_", ROW},
{"_L_", ROW}, {"LAZY", new string[]{ LIH, AEE, ZIH, }}, {"LOAD", new string[]{ LIH, OWE, " ", DIH, }}, {"LIMIT", new string[]{ LIH, IHH, MIH, IHH, TIH, }}, {"LOOP", new string[]{ LIH, OOO, " ", PIH, }}, {"LOL", new string[]{ LIH, UHH, RIH, FIH, " ", AHH, HOH, TIH, " ", LIH, AHH, HOH, DIH, }},
{"_L_", ROW}, {"LAZY", new string[]{ LIH, AEE, ZIH, EEE}}, {"LOAD", new string[]{ LIH, OWE, " ", DIH, }}, {"LIMIT", new string[]{ LIH, IHH, MIH, IHH, TIH, }}, {"LOOP", new string[]{ LIH, OOO, " ", PIH, }}, {"LOL", new string[]{ LIH, UHH, RIH, FIH, " ", AHH, HOH, TIH, " ", LIH, AHH, HOH, DIH, }},
{"_M_", ROW}, {"MADDEN", new string[]{ MIH, AHH, DIH, EHH, NIH, "", }}, {"MEME", new string[]{ MIH, EEE, " ", MIH, }}, {"MANUAL", new string[]{ MIH, AHH, NIH, OOO, LIH, ""}},
{"_N_", ROW}, {"NIGHT", new string[]{ NIH, EYE, " ", TIH, "", }}, {"NURSERY", new string[]{ NIH, RIH, " ", SIH, ERR, EEE, }}, {"NOW", new string[]{ NIH, OWE, WIH, }},
{"_O_", ROW}, {"OKAY", new string[]{ OWE, " ", KIH, AEE, }}, {"OVER", new string[]{ OWE, " ", VIH, ERR, }}, {"ON", new string[]{ HOH, NIH, }}, {"ONE", new string[]{ WIH, UHH, NIH, }}, {"ONCE", new string[]{ WIH, UHH, NIH, SIH, }}, {"OK", new string[]{ OWE, KIH, AEE, }}, {"ROUTE", new string[]{ RIH, OOO, TIH, }},
Expand Down
10 changes: 5 additions & 5 deletions OptionalDebugger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public OptionalDebugger()
static void Main()
{
OptionalDebugger debugger = new OptionalDebugger();
ChatManager entryPoint = new ChatManager (true);
ChatEntryPoint entryPoint = new ChatEntryPoint (true);
Encoding encode = Encoding.Unicode;
AttendanceManager.Debugging = true;
entryPoint.Initialise();
Expand All @@ -133,11 +133,11 @@ static void Main()
while (entryPoint.OutputManager.RunSpeechPlayback)
{
entryPoint.UpdateBeforeSimulation();
debugger.StoreResults (entryPoint.OutputManager.Speeches[0].Pronunciation.WordIsolator.CurrentWord, //use marek voice since we dont want intonations in the algorithm test.
entryPoint.OutputManager.Speeches[0].Results,
entryPoint.OutputManager.Speeches[0].Pronunciation.UsedDictionary);
debugger.StoreResults (entryPoint.OutputManager.Speeches[5].Pronunciation.WordIsolator.CurrentWord, //use marek voice since we dont want intonations in the algorithm test.
entryPoint.OutputManager.Speeches[5].CurrentResults,
entryPoint.OutputManager.Speeches[5].Pronunciation.UsedDictionary);
}
debugger.PrintResults (entryPoint.OutputManager.Speeches[0].Pronunciation.WrongFormatMatches, entryPoint.OutputManager.Speeches[0].Pronunciation.WrongFormatNonMatches);
debugger.PrintResults (entryPoint.OutputManager.Speeches[5].Pronunciation.WrongFormatMatches, entryPoint.OutputManager.Speeches[0].Pronunciation.WrongFormatNonMatches);
}

public string RollOutAdjacentWords()
Expand Down
110 changes: 68 additions & 42 deletions OutputManager.cs → Output/OutputManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using SETextToSpeechMod.Output;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace SETextToSpeechMod
Expand All @@ -9,12 +11,8 @@ public class OutputManager
public const int MAX_LETTERS = 100;
const int UPDATES_INTERVAL = 60;
const int TOTAL_SIMULTANEOUS_SPEECHES = 5;
const int DOESNT_EXIST = -1;

public bool RunSpeechPlayback { get; private set;}
int timer;
int[] typeIndexes;

const int DOESNT_EXIST = -1;

public Type LocalPlayersVoice
{
get
Expand All @@ -27,24 +25,35 @@ public Type LocalPlayersVoice
localVoiceField = value;
}
}
Type localVoiceField = PossibleOutputs.GLADOSType;

Type localVoiceField = PossibleOutputs.HawkingType;
/// <summary>
/// Same sized groups of sentence types are ordered by their position in struct PossibleOutputs.Collection
/// </summary>
public IList <SentenceFactory> Speeches
internal IList <SpeechTask> Speeches
{
get
{
return speechesField.AsReadOnly();
}
}
private List <SentenceFactory> speechesField = new List <SentenceFactory>(); //It's important to define the elements of the list only at compilation time.

private readonly List <SpeechTask> speechesField = new List <SpeechTask>();
private SoundPlayer soundPlayerRef;

TaskFactory taskFactory = new TaskFactory();

public static bool IsDebugging {get; private set;}
public bool RunSpeechPlayback { get; private set;}

int timer;
int[] typeIndexes;

public OutputManager (SoundPlayer inputEmitter, bool isDebugging)
{
if (IsDebugging == false)
{
IsDebugging = isDebugging;
}
soundPlayerRef = inputEmitter;
FactoryReset();
}
Expand All @@ -61,50 +70,57 @@ public void FactoryReset()
{
if (PossibleOutputs.Collection[i] == PossibleOutputs.MarekType)
{
speechesField.Add (new MarekVoice (soundPlayerRef));
speechesField.Add (new SpeechTask (new MarekVoice (soundPlayerRef)));
}

else if (PossibleOutputs.Collection[i] == PossibleOutputs.HawkingType)
{
speechesField.Add (new HawkingVoice (soundPlayerRef));
speechesField.Add (new SpeechTask (new MarekVoice (soundPlayerRef)));
}

else if (PossibleOutputs.Collection[i] == PossibleOutputs.GLADOSType)
{
speechesField.Add (new GladosVoice (soundPlayerRef));
//speechesField.Add new SpeechTask (new MarekVoice (soundPlayerRef)));
}
}
}
}
}

public async Task RunAsync()
public void Run()
{
await Task.Run (() => {
if (RunSpeechPlayback == true)
{
RunSpeechPlayback = false;
if (RunSpeechPlayback == true)
{
RunSpeechPlayback = false;

for (int i = 0; i < speechesField.Count; i++)
{
if (speechesField[i].Speech.IsFresh ||
speechesField[i].Speech.IsBusy)
{
RunSpeechPlayback = true;

for (int i = 0; i < speechesField.Count; i++)
{
if (speechesField[i].FinishedPlaying == false)
if (speechesField[i].ReturnInfo.IsCompleted == true) //assuming asyncCalls has matching length to speechesField
{
RunSpeechPlayback = true;
speechesField[i].Run();
taskFactory.StartNew (() => {
speechesField[i].RunAsync(); //fixed bug where there was a single returned task from all speeches.
},
speechesField[i].TaskCanceller.Token
);
}
}
}

if (timer <= 0) //im hoping that a little distance will prevent the oscillating position whch annoys ear drums.
{
timer = UPDATES_INTERVAL;
soundPlayerRef.UpdatePosition (AttendanceManager.LocalPlayer);
}

else
{
timer--;
}
if (timer <= 0) //a little timer will prevent the emitter from oscillating between your eyes.
{
timer = UPDATES_INTERVAL;
soundPlayerRef.UpdatePosition (AttendanceManager.LocalPlayer);
}
});

else
{
timer--;
}
}
}

/// <summary>
Expand All @@ -128,7 +144,8 @@ private int GetOutputTypesIndex (string scrutinizedTypeName)
}

/// <summary>
/// The only accepted types are contained in public struct PossibleOutputs
/// Resets the next speech within the group of the same voice type, instead of incurring performance costs but instantiating every time.
/// The only accepted types are contained in public struct PossibleOutputs.
/// </summary>
/// <param name="validVoiceType"></param>
/// <param name="sentence"></param>
Expand All @@ -145,12 +162,21 @@ public void CreateNewSpeech (string validVoiceTypeName, string inputSentence)
{
typeIndexes[currentTypeIndex] = 0;
}
int NewSpeechIndex = firstTypeInstance + typeIndexes[currentTypeIndex];
speechesField[NewSpeechIndex].FactoryReset (inputSentence); //The purpose of this method is to reuse instances of sentencefactory instead of instantiating every new sentence.
int newSpeechIndex = firstTypeInstance + typeIndexes[currentTypeIndex];


while (asyncCalls[newSpeechIndex].IsCompleted == false) { }
speechesField[newSpeechIndex].Speech.FactoryReset (inputSentence); //reuses instances of sentencefactory instead of instantiating every new sentence.
typeIndexes[currentTypeIndex]++;
}
}
}


public void DisposeOfUnsafe()
{
for (int i = 0; i < speechesField.Count; i++)
{
speechesField[i].TaskCanceller.Dispose();
}
}
}
}
9 changes: 5 additions & 4 deletions PossibleOutputs.cs → Output/PossibleOutputs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace SETextToSpeechMod
static class PossibleOutputs
{
public static Type MarekType { get { return typeof (MarekVoice); } }
public static Type HawkingType { get{ return typeof (HawkingVoice); } }
public static Type GLADOSType { get{ return typeof (GladosVoice); } }
public static Type HawkingType { get { return typeof (HawkingVoice); } }
public static Type GLADOSType { get { return typeof (GladosVoice); } }

public static IList <Type> Collection
{
Expand All @@ -16,11 +16,12 @@ public static IList <Type> Collection
return allOptionsField.AsReadOnly();
}
}

private static List <Type> allOptionsField = new List<Type>()
{
MarekType, //marek must be first for optionaldebugger to work
HawkingType,
GLADOSType,
HawkingType,
//GLADOSType,
};
public static int AutoSignatureSize { get; }

Expand Down
44 changes: 20 additions & 24 deletions SoundPlayer.cs → Output/SoundPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
using VRage.Game.Entity;
using VRageMath;
using VRage.Game.ModAPI;
using System.Threading.Tasks;

namespace SETextToSpeechMod
{
public class SoundPlayer
{
const int CHANCE_OF_CLANG = 10000; //cannot be zero
const string BONK = "BONK";
const string SPACE = "SPACE";
const string BONK = "BONK";

MyEntity3DSoundEmitter TTSEmitter;
Random numberGenerator = new Random();

private float volume = 0.6f;
private const float DISTANCE = 500.0f;

private bool debugging;
private bool playInRealisticMode;
private readonly bool debugging;
private readonly bool playInRealisticMode;

public SoundPlayer (bool isDebugging, bool inputRealisticModeOption)
{
Expand Down Expand Up @@ -80,37 +80,33 @@ public void UpdateVolume (float newVolume)
}
}

public bool PlaySentence (List <TimelineClip> inputTimeline, int currentTick)
{
bool hasFinished = false;
public async Task PlaySentence (List <TimelineClip> timeline)
{
int rngBonk = numberGenerator.Next (CHANCE_OF_CLANG);

if (rngBonk == CHANCE_OF_CLANG - 1) //repent you fucking sinner. CLANG
{
PlayClip (BONK);
}

if (inputTimeline.Count > 0)
if (timeline.Count > 0)
{
while (inputTimeline.Count > 0 &&
inputTimeline[0].StartPoint <= currentTick)
{
if (inputTimeline[0].ClipsSound != SPACE)
int currentClip = default (int);
var timelineClone = timeline.ToArray(); //assume that timeline is kill during Task.Run

await Task.Run (() => {
for (int i = 0; i <= timelineClone[timelineClone.Length - 1].StartPoint; i++)
{
PlayClip (inputTimeline[0].ClipsSound);
}
inputTimeline.RemoveAt (0);
}
}

else
{
hasFinished = true;
}
return hasFinished;
if (i == timelineClone[currentClip].StartPoint)
{
PlayClip (timelineClone[currentClip].ClipsSound);
}
}
});
}
}

private void PlayClip (string clip)
private void PlayClip (string clip)
{
if (debugging == false)
{
Expand Down
Loading

0 comments on commit 0e6d6d5

Please sign in to comment.