Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Assets/UAP/NativePlugins~/WindowsTTS/WindowsTTS.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#endif

#include <mutex>
#include <condition_variable>
#include <list>
#include <thread>

Expand All @@ -22,6 +23,7 @@ namespace WindowsVoice {
}

std::mutex theMutex;
std::condition_variable cv;
std::list<wchar_t*> theSpeechQueue;
std::thread* theSpeechThread;
bool stopSpeech;
Expand Down
48 changes: 29 additions & 19 deletions Assets/UAP/NativePlugins~/WindowsTTS/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,45 @@
#include <Windows.h>


namespace WindowsVoice
namespace WindowsVoice
{

int Volume = 100;
int Rate = 0;

bool IsSpeaking = false;
ISpVoice * pVoice = NULL;
ISpVoice* pVoice = NULL;

void SpeechThreadFunc()
{
theMutex.lock();
//SpeechSynthesizer* synth = new SpeechSynthesizer();

SPVOICESTATUS *pStatus = new SPVOICESTATUS();
SPVOICESTATUS* pStatus = new SPVOICESTATUS();

if (FAILED(::CoInitializeEx(NULL, COINITBASE_MULTITHREADED)))
{
//std::cout<<"Failed to initialize COM for Voice.\n";
theMutex.unlock();
return;
}

HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
pVoice->SetRate(Rate);
pVoice->SetVolume(Volume);
if (!SUCCEEDED(hr))
{
LPVOID pText = 0;

::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&pText, 0, NULL);
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&pText, 0, NULL);
//std::cout<<"Failed to create voice instance. Error: "<<pText<<std::endl;
LocalFree(pText);
theMutex.unlock();
return;
}

cv.notify_all();
theMutex.unlock();

// Enumerate available voices
//hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &m_VoicesEnum);
Expand Down Expand Up @@ -86,10 +90,10 @@ namespace WindowsVoice
if (wText)
{
//SetNotifyCallbackFunction
pVoice->Speak(wText, SPF_IS_NOT_XML | SPF_ASYNC, NULL);
// Sleep(250);
delete[] priorText;
priorText = wText;
pVoice->Speak(wText, SPF_IS_NOT_XML | SPF_ASYNC, NULL);
// Sleep(250);
delete[] priorText;
priorText = wText;
}
}
pVoice->Release();
Expand All @@ -103,10 +107,11 @@ namespace WindowsVoice
if (text)
{
int len = strlen(text) + 1;
wchar_t *wText = new wchar_t[len];
wchar_t* wText = new wchar_t[len];

memset(wText, 0, len);
::MultiByteToWideChar(CP_ACP, NULL, text, -1, wText, len);
// Use CP_UTF8 for proper unicode support
::MultiByteToWideChar(CP_UTF8, NULL, text, -1, wText, len);

theMutex.lock();
theSpeechQueue.push_back(wText);
Expand All @@ -122,7 +127,9 @@ namespace WindowsVoice
shouldTerminate = false;
stopSpeech = false;

std::unique_lock<std::mutex> lk(theMutex);
theSpeechThread = new std::thread(WindowsVoice::SpeechThreadFunc);
while (pVoice == NULL) cv.wait(lk);
}

//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -159,6 +166,7 @@ namespace WindowsVoice
{
theMutex.lock();
Rate = rate;
pVoice->SetRate(Rate);
theMutex.unlock();
}

Expand All @@ -182,20 +190,22 @@ namespace WindowsVoice
{
// convert char to WCHAR
int len = strlen(voiceDescription) + 1;
wchar_t *wText = new wchar_t[len];
wchar_t* wText = new wchar_t[len];
memset(wText, 0, len);
::MultiByteToWideChar(CP_ACP, NULL, voiceDescription, -1, wText, len);

// Try to find a matching voice
ISpObjectToken* cpToken(NULL);
SpFindBestToken(SPCAT_VOICES, wText, L"", &cpToken);

// Set the voice
theMutex.lock();
pVoice->SetVoice(cpToken);
theMutex.unlock();

cpToken->Release();
//if there's a valid token
if (cpToken) {
// Set the voice
theMutex.lock();
pVoice->SetVoice(cpToken);
theMutex.unlock();
cpToken->Release();
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions Assets/UAP/NativePlugins~/WindowsTTS/framework.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
5 changes: 5 additions & 0 deletions Assets/UAP/NativePlugins~/WindowsTTS/pch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header

#include "pch.h"

// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
13 changes: 13 additions & 0 deletions Assets/UAP/NativePlugins~/WindowsTTS/pch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.

#ifndef PCH_H
#define PCH_H

// add headers that you want to pre-compile here
#include "framework.h"

#endif //PCH_H
16 changes: 16 additions & 0 deletions Assets/UAP/Plugins/MacOS/MacOSTTS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class MacOSTTS : MonoBehaviour
{
public static MacOSTTS instance = null;
bool m_IsSpeaking = false;
private static string m_VoiceName = null;

#if (UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX)
Process m_VoiceProcess = null;
Expand Down Expand Up @@ -57,6 +58,10 @@ IEnumerator SpeakText(string textToSpeak)
textToSpeak = textToSpeak.Replace('"', '\'');
int speechRate = (int)((UAP_AccessibilityManager.GetSpeechRate() / 100.0f) * 175 * 2);
string parameters = "-r " + speechRate + " " + '"' + textToSpeak + '"';
if (m_VoiceName != null)
{
parameters = "-v " + m_VoiceName + " " + parameters;
}

m_VoiceProcess = new System.Diagnostics.Process();
m_VoiceProcess.StartInfo.FileName = "say";
Expand Down Expand Up @@ -137,4 +142,15 @@ void OnDestroy()

//////////////////////////////////////////////////////////////////////////

/// <summary>
/// Sets the voice used by the say command
/// </summary>
/// <param name="name">
/// Name of the voice to be used.
/// List of available voices can be found by using the terminal command "say -v '?'".
/// </param>
public static void SetVoice(string name)
{
m_VoiceName = name;
}
}
Binary file modified Assets/UAP/Plugins/x86/WindowsTTS.dll
Binary file not shown.
47 changes: 36 additions & 11 deletions Assets/UAP/Plugins/x86_64/WindowsTTS.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System.Collections.Generic;

public class WindowsTTS : MonoBehaviour
{
Expand All @@ -15,10 +16,12 @@ public class WindowsTTS : MonoBehaviour
public static extern void AddToSpeechQueue(string s);
//[DllImport("WindowsTTS")]
//public static extern void SetVolume(int volume);
//[DllImport("WindowsTTS")]
//public static extern void SetRate(int rate);
[DllImport("WindowsTTS")]
public static extern void SetRate(int rate);
[DllImport("WindowsTTS")]
public static extern bool IsVoiceSpeaking();
[DllImport("WindowsTTS")]
public static extern void SetVoiceSAPI(string s);

[DllImport("nvdaControllerClient")]
internal static extern int nvdaController_testIfRunning();
Expand Down Expand Up @@ -78,7 +81,7 @@ void Start()
}

//////////////////////////////////////////////////////////////////////////

public static void Speak(string msg)
{
if (m_UseNVDA)
Expand All @@ -94,6 +97,20 @@ public static void Speak(string msg)

//////////////////////////////////////////////////////////////////////////

/// <summary>
/// Sets the voice used by the SAPI API
/// </summary>
/// <param name="name">Name of the voice to be used. Can be found under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\[voice]\Attributes.</param>
public static void SetVoice(string name)
{
if (!m_UseNVDA)
{
SetVoiceSAPI("Name=" + name);
}
}

//////////////////////////////////////////////////////////////////////////

public static void Stop()
{
if (m_UseNVDA)
Expand Down Expand Up @@ -133,22 +150,30 @@ void Update()
m_NVDAIsSpeakingTimer -= Time.unscaledDeltaTime;
}

/*
//////////////////////////////////////////////////////////////////////////
/*
//////////////////////////////////////////////////////////////////////////

public static void SetSpeechVolume(int volume)
{
SetVolume(volume);
}
public static void SetSpeechVolume(int volume)
{
SetVolume(volume);
}

*/

//////////////////////////////////////////////////////////////////////////

public static void SetSpeechRate(int rate)
{
//if using SAPI
if (!m_UseNVDA)
{
//normalize the standard 1-100 rate to SAPI -10 to 10 range
rate = -10 + (int)((rate - 1) * 0.202);
}
SetRate(rate);
}
*/


//////////////////////////////////////////////////////////////////////////

void OnDestroy()
Expand Down
Binary file modified Assets/UAP/Plugins/x86_64/WindowsTTS.dll
Binary file not shown.
30 changes: 24 additions & 6 deletions Assets/UAP/Scripts/Core/UAP_AccessibilityManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1348,7 +1348,8 @@ void ReadType()
//if (!m_CurrentItem.m_Object.IsInteractable())
// SayAudio(m_DisabledAsAudio, "Disabled", UAP_AudioQueue.EAudioType.Element_Hint);
break;
};
}
;
}

//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1420,7 +1421,8 @@ void ReadHint()
else
SayAudio(null, Localize_Internal("Desktop_HintSlider"), UAP_AudioQueue.EAudioType.Element_Hint, m_CurrentItem.m_Object.m_AllowVoiceOver);
break;
};
}
;
}

}
Expand Down Expand Up @@ -1730,7 +1732,7 @@ private void ActivateContainer_Internal(AccessibleUIGroupRoot container, bool ac

if (m_ActiveContainers[0] == container && container.m_AutoRead)
{
ReadFromTop();
ReadFromTop();
}
else
{
Expand All @@ -1745,7 +1747,7 @@ private void ActivateContainer_Internal(AccessibleUIGroupRoot container, bool ac

if (m_ActiveContainers[m_ActiveContainerIndex] == container && container.m_AutoRead)
{
ReadFromTop();
ReadFromTop();
}
else
{
Expand Down Expand Up @@ -4545,7 +4547,7 @@ static public bool MakeActiveContainer(AccessibleUIGroupRoot container, bool for

if (!instance.m_ActiveContainers.Contains(container))
{
if(instance.m_DebugOutput && m_IsEnabled)
if (instance.m_DebugOutput && m_IsEnabled)
Debug.LogWarning("[Accessibility] Trying to select an item in a container that is inactive. Ignoring call.");
return false;
}
Expand Down Expand Up @@ -4706,6 +4708,22 @@ static public void StopSpeaking()

//////////////////////////////////////////////////////////////////////////

/// <summary>
/// Set the voice used by the screen reader.
/// Works with Windows SAPI TTS and Mac OS TTS, but the available voices are different for each.
/// For windows, available voices can be found in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\[voice]\Attributes\Name
/// For mac, available voices can be found by running the command "say -v '?'".
/// </summary>
/// <param name="voice">Name of the voice to be used</param>
/// <returns></returns>
static public string SetVoice(string voice)
{
Initialize();
return instance.m_AudioQueue.SetVoice(voice);
}

//////////////////////////////////////////////////////////////////////////

/// <summary>
/// This function is called from the Accessible UI component if the <i>Is Localization Key</i> checkbox is ticked.
///
Expand Down Expand Up @@ -4771,7 +4789,7 @@ static public string FormatNumberToCurrentLocale(ulong intNumber)
//Debug.Log(CultureInfo.CurrentCulture.ToString() + " " + formattedNumber);
return formattedNumber;
}

static public string FormatNumberToCurrentLocale(double floatNumber)
{
string formattedNumber;// = string.Format(CultureInfo.CurrentCulture, "{0:n0}", intNumber);
Expand Down
Loading