1 /* Copyright (C) 2012, 2013  Olga Yakovleva <yakovleva.o.v@gmail.com> */
2 
3 /* This program is free software: you can redistribute it and/or modify */
4 /* it under the terms of the GNU Lesser General Public License as published by */
5 /* the Free Software Foundation, either version 2.1 of the License, or */
6 /* (at your option) any later version. */
7 
8 /* This program is distributed in the hope that it will be useful, */
9 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
10 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the */
11 /* GNU Lesser General Public License for more details. */
12 
13 /* You should have received a copy of the GNU Lesser General Public License */
14 /* along with this program.  If not, see <http://www.gnu.org/licenses/>. */
15 
16 #include <new>
17 #include "utils.hpp"
18 #include "ISpTTSEngineImpl.hpp"
19 #include "SpeakImpl.hpp"
20 
21 namespace RHVoice
22 {
23   namespace sapi
24   {
SetObjectToken(ISpObjectToken * pToken)25     STDMETHODIMP ISpTTSEngineImpl::SetObjectToken(ISpObjectToken *pToken)
26     {
27       if(pToken==0)
28         return E_INVALIDARG;
29       try
30         {
31           ISpDataKeyPtr attr;
32           if(FAILED(pToken->OpenKey(L"Attributes",&attr)))
33             return E_INVALIDARG;
34           utils::out_ptr<wchar_t> name(CoTaskMemFree);
35           if(FAILED(attr->GetStringValue(L"Name",name.address())))
36             return E_INVALIDARG;
37           voice_profile new_profile=get_engine()->create_voice_profile(utils::wstring_to_string(name.get()));
38           if(new_profile.empty())
39             return E_INVALIDARG;
40           profile=new_profile;
41           token=pToken;
42           return S_OK;
43         }
44       catch(const std::bad_alloc&)
45         {
46           return E_OUTOFMEMORY;
47         }
48       catch(...)
49         {
50           return E_UNEXPECTED;
51         }
52     }
53 
GetObjectToken(ISpObjectToken ** ppToken)54     STDMETHODIMP ISpTTSEngineImpl::GetObjectToken(ISpObjectToken **ppToken)
55     {
56       if(ppToken==0)
57         return E_POINTER;
58       *ppToken=0;
59       if(token)
60         {
61           token.AddRef();
62           *ppToken=token.GetInterfacePtr();
63           return S_OK;
64         }
65       else
66         return E_UNEXPECTED;
67     }
68 
GetOutputFormat(const GUID * pTargetFmtId,const WAVEFORMATEX * pTargetWaveFormatEx,GUID * pOutputFormatId,WAVEFORMATEX ** ppCoMemOutputWaveFormatEx)69     STDMETHODIMP ISpTTSEngineImpl::GetOutputFormat([[maybe_unused]] const GUID *pTargetFmtId, [[maybe_unused]] const WAVEFORMATEX *pTargetWaveFormatEx,GUID *pOutputFormatId,WAVEFORMATEX **ppCoMemOutputWaveFormatEx)
70     {
71       if(pOutputFormatId==0)
72         return E_POINTER;
73       if(ppCoMemOutputWaveFormatEx==0)
74         return E_POINTER;
75       *pOutputFormatId=SPDFID_WaveFormatEx;
76       *ppCoMemOutputWaveFormatEx=0;
77       WAVEFORMATEX *pwfex=reinterpret_cast<WAVEFORMATEX*>(CoTaskMemAlloc(sizeof(WAVEFORMATEX)));
78       if(pwfex==0)
79         return E_OUTOFMEMORY;
80       pwfex->wFormatTag=0x0001;
81       pwfex->nChannels=1;
82       pwfex->nSamplesPerSec=((get_engine()->quality==quality_min)?16000:24000);
83       pwfex->wBitsPerSample=16;
84       pwfex->nBlockAlign=pwfex->nChannels*pwfex->wBitsPerSample/8;
85       pwfex->nAvgBytesPerSec=pwfex->nSamplesPerSec*pwfex->nBlockAlign;
86       pwfex->cbSize=0;
87       *ppCoMemOutputWaveFormatEx=pwfex;
88       return S_OK;
89     }
90 
Speak(DWORD dwSpeakFlags,REFGUID rguidFormatId,const WAVEFORMATEX * pWaveFormatEx,const SPVTEXTFRAG * pTextFragList,ISpTTSEngineSite * pOutputSite)91     STDMETHODIMP ISpTTSEngineImpl::Speak([[maybe_unused]] DWORD dwSpeakFlags, [[maybe_unused]] REFGUID rguidFormatId, [[maybe_unused]] const WAVEFORMATEX *pWaveFormatEx,const SPVTEXTFRAG *pTextFragList,ISpTTSEngineSite *pOutputSite)
92     {
93       if(pTextFragList==0)
94         return E_INVALIDARG;
95       if(pOutputSite==0)
96         return E_INVALIDARG;
97       try
98         {
99           SpeakImpl::init_params p;
100           p.input=pTextFragList;
101           p.caller=pOutputSite;
102           p.profile=profile;
103           SpeakImpl s(p);
104           s();
105           return S_OK;
106         }
107       catch(const std::bad_alloc&)
108         {
109           return E_OUTOFMEMORY;
110         }
111       catch(...)
112         {
113           return E_UNEXPECTED;
114         }
115     }
116   }
117 }
118