351 lines
10 KiB
C++
351 lines
10 KiB
C++
|
/******************************************************************************
|
||
|
* RegVoices.cpp *
|
||
|
*---------------*
|
||
|
*
|
||
|
* This code does not ship. Based on MC's code for msttsdrv.
|
||
|
*
|
||
|
* This code creates the registry entries for the TTS voices. The
|
||
|
* datafiles registered here are the ones checked in the slm source
|
||
|
* tree. This is not done using a reg file because we need to compute
|
||
|
* the absolute path of the datafiles which can be different on different
|
||
|
* machines because of different root slm directories.
|
||
|
*------------------------------------------------------------------------------
|
||
|
* Copyright (C) 2000 Microsoft Corporation Date: 03/20/00
|
||
|
* All Rights Reserved
|
||
|
*
|
||
|
********************************************************************* PACOG ***/
|
||
|
#include <windows.h>
|
||
|
#include <atlbase.h>
|
||
|
#include "sphelper.h"
|
||
|
#include "spddkhlp.h"
|
||
|
#include "getopt.h"
|
||
|
#include <spunicode.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
|
||
|
#define SYNTAX fprintf (stderr, "RegVoices [-u (UK Eng voice)] [voicesPath]\n")
|
||
|
|
||
|
#define DIR_LEVELS_BACK 4 // Back levels to 'TrueTalk' directory
|
||
|
|
||
|
|
||
|
static HRESULT CreateVoiceSubKey(
|
||
|
const WCHAR * pszSubKeyName,
|
||
|
const WCHAR * pszDescription,
|
||
|
BOOL fVendorDefault,
|
||
|
const WCHAR * pszLanguage,
|
||
|
const WCHAR * pszGender,
|
||
|
const WCHAR * pszAge,
|
||
|
const WCHAR * pszVoicePath,
|
||
|
const WCHAR * pszVoiceName,
|
||
|
const WCHAR * pszLexPath,
|
||
|
double dGain);
|
||
|
|
||
|
const CLSID CLSID_TrueTalk = {0x8E67289A,0x609C,0x4B68,{0x91,0x8B,0x5C,0x35,0x2D,0x9E,0x5D,0x38}};
|
||
|
const CLSID CLSID_PhoneConverter = {0x9185F743,0x1143,0x4C28,{0x86,0xB5,0xBF,0xF1,0x4F,0x20,0xE5,0xC8}};
|
||
|
const WCHAR* g_UKPhoneMap = L"- 0001 ! 0002 & 0003 , 0004 . 0005 ? 0006 _ 0007 1 0008 2 0009 AA 000A AE 000B AH 000C AO 000D AW 000E AX 000F AY 0010 B 0011 CH 0012 D 0013 DH 0014 EH 0015 ER 0016 EY 0017 F 0018 G 0019 H 001A IH 001B IY 001C JH 001D K 001E L 001F M 0020 N 0021 NG 0022 OW 0023 OY 0024 P 0025 R 0026 S 0027 SH 0028 T 0029 TH 002A UH 002B UW 002C V 002D W 002E Y 002F Z 0030 ZH 0031 EX 0032 UR 0033";
|
||
|
|
||
|
//-- Static
|
||
|
CSpUnicodeSupport g_Unicode;
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* main *
|
||
|
*-------*
|
||
|
* Description:
|
||
|
* Locate the abs path to Simon, etc.
|
||
|
* and register them in the system registry.
|
||
|
*
|
||
|
******************************************************************* PACOG ***/
|
||
|
int wmain (int argc, wchar_t* argv[])
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
WCHAR szVoiceDataPath[MAX_PATH];
|
||
|
WCHAR szDictDataPath[MAX_PATH];
|
||
|
bool fUkVoice = false;
|
||
|
CWGetOpt getOpt;
|
||
|
int iChar;
|
||
|
|
||
|
CoInitialize(NULL);
|
||
|
|
||
|
getOpt.Init(argc, argv, L"u");
|
||
|
|
||
|
while ( (iChar = getOpt.NextOption()) != EOF )
|
||
|
{
|
||
|
switch (iChar)
|
||
|
{
|
||
|
case L'u':
|
||
|
fUkVoice = true;
|
||
|
break;
|
||
|
case L'?':
|
||
|
default:
|
||
|
SYNTAX;
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch (argc - getOpt.OptInd())
|
||
|
{
|
||
|
case 1:
|
||
|
wcscpy (szVoiceDataPath, argv[getOpt.OptInd()]);
|
||
|
wcscat (szVoiceDataPath, L"\\" );
|
||
|
break;
|
||
|
case 0:
|
||
|
//-- Get the exe's location...
|
||
|
if( !g_Unicode.GetModuleFileName(NULL, szVoiceDataPath, MAX_PATH) )
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
//-- ...and derive abs path to VOICE and DICT data
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
WCHAR *psz;
|
||
|
// modulename is "<sapi5>\Src\TTS\TrueTalk\RegVoices\Obj\i386\RegVoices.exe"
|
||
|
// data is at "<sapi5>\Src\TTS\TrueTalk\Voices\"
|
||
|
for ( int i = 0; i < DIR_LEVELS_BACK; i++ )
|
||
|
{
|
||
|
psz = wcsrchr( szVoiceDataPath, '\\' );
|
||
|
if (psz != 0)
|
||
|
{
|
||
|
*psz= 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wcscat( szVoiceDataPath, L"\\Voices\\" );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
SYNTAX;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
wcscat( wcscpy(szDictDataPath, szVoiceDataPath), L"Dict");
|
||
|
|
||
|
//-- Register the TrueTalk voices..
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
hr = CreateVoiceSubKey(L"TTSimonMin",
|
||
|
L"TrueTalk Simon Min",
|
||
|
FALSE,
|
||
|
L"409;9",
|
||
|
L"Male",
|
||
|
L"Adult",
|
||
|
szVoiceDataPath,
|
||
|
L"Simon\\sa8kMin.sfont",
|
||
|
szDictDataPath,
|
||
|
3.0);
|
||
|
}
|
||
|
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
hr = CreateVoiceSubKey(L"TTSimon150",
|
||
|
L"TrueTalk Simon 150",
|
||
|
FALSE,
|
||
|
L"409;9",
|
||
|
L"Male",
|
||
|
L"Adult",
|
||
|
szVoiceDataPath,
|
||
|
L"Simon\\sa8k150.sfont",
|
||
|
szDictDataPath,
|
||
|
3.0);
|
||
|
}
|
||
|
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
hr = CreateVoiceSubKey(L"TTMaryMin",
|
||
|
L"TrueTalk Mary Min",
|
||
|
FALSE,
|
||
|
L"409;9",
|
||
|
L"Female",
|
||
|
L"Adult",
|
||
|
szVoiceDataPath,
|
||
|
L"Mary\\ml8kMin.sfont",
|
||
|
szDictDataPath,
|
||
|
3.0);
|
||
|
}
|
||
|
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
hr = CreateVoiceSubKey(L"TTMary150",
|
||
|
L"TrueTalk Mary 150",
|
||
|
FALSE,
|
||
|
L"409;9",
|
||
|
L"Female",
|
||
|
L"Adult",
|
||
|
szVoiceDataPath,
|
||
|
L"Mary\\ml8k150.sfont",
|
||
|
szDictDataPath,
|
||
|
3.0);
|
||
|
}
|
||
|
|
||
|
if (fUkVoice)
|
||
|
{
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
hr = CreateVoiceSubKey(L"TTDianeMin",
|
||
|
L"TrueTalk Diane Min",
|
||
|
FALSE,
|
||
|
L"809;9",
|
||
|
L"Female",
|
||
|
L"Adult",
|
||
|
szVoiceDataPath,
|
||
|
L"Diane\\dk8kMin.sfont",
|
||
|
szDictDataPath,
|
||
|
5.0);
|
||
|
}
|
||
|
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
hr = CreateVoiceSubKey(L"TTDiane150",
|
||
|
L"TrueTalk Diane 150",
|
||
|
FALSE,
|
||
|
L"809;9",
|
||
|
L"Female",
|
||
|
L"Adult",
|
||
|
szVoiceDataPath,
|
||
|
L"Diane\\dk8k150.sfont",
|
||
|
szDictDataPath,
|
||
|
5.0);
|
||
|
}
|
||
|
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
CComPtr<ISpObjectToken> cpToken;
|
||
|
CComPtr<ISpDataKey> cpDataKeyAttribs;
|
||
|
|
||
|
hr = SpCreateNewTokenEx(
|
||
|
SPCAT_PHONECONVERTERS,
|
||
|
L"English (UK)",
|
||
|
&CLSID_PhoneConverter,
|
||
|
L"UK English Phone Converter",
|
||
|
0x0,
|
||
|
NULL,
|
||
|
&cpToken,
|
||
|
&cpDataKeyAttribs);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpToken->SetStringValue(L"PhoneMap", g_UKPhoneMap);
|
||
|
}
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpDataKeyAttribs->SetStringValue(L"Language", L"809");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
|
||
|
CoUninitialize();
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* CreateVoiceSubKey *
|
||
|
*--------------------*
|
||
|
* Description:
|
||
|
* Each TTS voice gets installed under one registry sub-key.
|
||
|
* This function installs the single voice from the passed params.
|
||
|
*
|
||
|
********************************************************************** MC ***/
|
||
|
HRESULT CreateVoiceSubKey(
|
||
|
const WCHAR * pszSubKeyName,
|
||
|
const WCHAR * pszDescription,
|
||
|
BOOL fVendorDefault,
|
||
|
const WCHAR * pszLanguage,
|
||
|
const WCHAR * pszGender,
|
||
|
const WCHAR * pszAge,
|
||
|
const WCHAR * pszVoicePath,
|
||
|
const WCHAR * pszVoiceName,
|
||
|
const WCHAR * pszDictPath,
|
||
|
double dGain)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
CComPtr<ISpObjectToken> cpToken;
|
||
|
CComPtr<ISpDataKey> cpDataKeyAttribs;
|
||
|
|
||
|
hr = SpCreateNewTokenEx(
|
||
|
SPCAT_VOICES,
|
||
|
pszSubKeyName,
|
||
|
&CLSID_TrueTalk,
|
||
|
pszDescription,
|
||
|
0x409,
|
||
|
pszDescription,
|
||
|
&cpToken,
|
||
|
&cpDataKeyAttribs);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpDataKeyAttribs->SetStringValue(L"Name", pszDescription);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpDataKeyAttribs->SetStringValue(L"Vendor", L"Microsoft");
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpDataKeyAttribs->SetStringValue(L"Language", pszLanguage);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpDataKeyAttribs->SetStringValue(L"Age", pszAge);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpDataKeyAttribs->SetStringValue(L"Gender", pszGender);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr) && fVendorDefault)
|
||
|
{
|
||
|
hr = cpDataKeyAttribs->SetStringValue(L"VendorDefault", L"");
|
||
|
}
|
||
|
|
||
|
WCHAR szVoiceDataPath[MAX_PATH];
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
//--------------------------------
|
||
|
// Voice DATA file location
|
||
|
//--------------------------------
|
||
|
wcscpy(szVoiceDataPath, pszVoicePath);
|
||
|
wcscat(szVoiceDataPath, pszVoiceName);
|
||
|
|
||
|
hr = cpToken->SetStringValue(L"Sfont", szVoiceDataPath);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = cpToken->SetStringValue(L"Dictionary", pszDictPath);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
WCHAR pszGain[20];
|
||
|
|
||
|
swprintf (pszGain, L"%.1f", dGain);
|
||
|
hr = cpToken->SetStringValue(L"Gain", pszGain);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|