windows-nt/Source/XPSP1/NT/enduser/speech/tts/truetalk/regvoices/regvoices.cpp
2020-09-26 16:20:57 +08:00

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;
}