Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

418 lines
11 KiB

  1. /******************************************************************************
  2. * Backend.cpp *
  3. *-------------*
  4. *
  5. *------------------------------------------------------------------------------
  6. * Copyright (C) 1998 Entropic, Inc
  7. * Copyright (C) 2000 Microsoft Corporation Date: 03/02/00
  8. * All Rights Reserved
  9. *
  10. ********************************************************************* PACOG ***/
  11. #include "backend.h"
  12. #include "tips.h"
  13. #include "SynthUnit.h"
  14. #include "SpeakerData.h"
  15. #include "vapiIo.h"
  16. #include <windows.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <assert.h>
  20. static const int DEFAULT_F0_SAMPFREQ = 200;
  21. static const double SYNTH_PROPORTION = .1;
  22. class CBEndImp : public CBackEnd
  23. {
  24. public:
  25. CBEndImp();
  26. ~CBEndImp();
  27. int LoadTable (const char* pszFilePath, int iDebug = 0);
  28. int GetSampFreq ();
  29. void SetGain (double dGain);
  30. void GetSpeakerInfo (int* piBaseLine, int* piRefLine, int* piTopLine);
  31. void SetF0SampFreq (int iF0SampFreq = DEFAULT_F0_SAMPFREQ);
  32. int NewPhoneString (Phone* phList, int nPh, float* newF0, int nNewF0);
  33. int OutputPending ();
  34. int GenerateOutput (short** ppnSamples, int* piNumSamples);
  35. int GetChunk (ChkDescript** ppChunk);
  36. bool GetPhoneSetFlag ();
  37. void SetFrontEndFlag () { m_pSlm->SetFrontEndFlag(); }
  38. private:
  39. static const int m_iDefSampFreq;
  40. CSlm* m_pSlm;
  41. CTips* m_pTips;
  42. int m_iNumUnits;
  43. int m_iCurrUnit;
  44. int m_iF0SampFreq;
  45. float* m_pflF0;
  46. short* m_pnSynthBuff;
  47. int m_iSynthBuffSamples;
  48. short* m_pnOverflow;
  49. int m_iOverflowCurSamples;
  50. int m_iOverflowMaxSamples;
  51. int m_iPrevSamples;
  52. };
  53. const int CBEndImp::m_iDefSampFreq = 8000;
  54. /*****************************************************************************
  55. * CBackEnd::ClassFactory *
  56. *------------------------*
  57. * Description:
  58. *
  59. ******************************************************************* PACOG ***/
  60. CBackEnd* CBackEnd::ClassFactory()
  61. {
  62. return new CBEndImp;
  63. }
  64. /*****************************************************************************
  65. * CBEndImp::CBEndImp *
  66. *--------------------*
  67. * Description:
  68. *
  69. ******************************************************************* PACOG ***/
  70. CBEndImp::CBEndImp()
  71. {
  72. int iSlmOptions = CSlm::UseGain | CSlm::Blend | CSlm::DynSearch | CSlm::UseTargetF0;
  73. int iTipsOptions = 0;
  74. if ( (m_pSlm = CSlm::ClassFactory(iSlmOptions)) == NULL)
  75. {
  76. goto error;
  77. }
  78. if ((m_pTips = new CTips(iTipsOptions)) == NULL)
  79. {
  80. goto error;
  81. }
  82. m_iPrevSamples = 0;
  83. m_iSynthBuffSamples = 0;
  84. m_pnSynthBuff = NULL;
  85. m_pnOverflow = NULL;
  86. m_iOverflowCurSamples = 0;
  87. m_iOverflowMaxSamples = 0;
  88. m_pTips->Init(VAPI_PCM16, m_iDefSampFreq);
  89. m_iNumUnits = 0;
  90. m_iCurrUnit = 0;
  91. m_iF0SampFreq = DEFAULT_F0_SAMPFREQ;
  92. m_pflF0 = NULL;
  93. return;
  94. error:
  95. if ( m_pTips )
  96. {
  97. delete m_pTips;
  98. m_pTips = NULL;
  99. }
  100. return;
  101. }
  102. /*****************************************************************************
  103. * CBEndImp::~CBEndImp *
  104. *---------------------*
  105. * Description:
  106. *
  107. ******************************************************************* PACOG ***/
  108. CBEndImp::~CBEndImp ()
  109. {
  110. if (m_pSlm)
  111. {
  112. delete m_pSlm;
  113. }
  114. if (m_pTips)
  115. {
  116. delete m_pTips;
  117. }
  118. if ( m_pflF0 )
  119. {
  120. delete[] m_pflF0;
  121. m_pflF0 = NULL;
  122. }
  123. if ( m_pnSynthBuff )
  124. {
  125. delete [] m_pnSynthBuff;
  126. m_pnSynthBuff = NULL;
  127. }
  128. if ( m_pnOverflow )
  129. {
  130. delete [] m_pnOverflow;
  131. m_pnOverflow = NULL;
  132. }
  133. }
  134. /*****************************************************************************
  135. * CBEndImp::LoadTable *
  136. *---------------------*
  137. * Description:
  138. *
  139. ******************************************************************* PACOG ***/
  140. int CBEndImp::LoadTable (const char* pszFilePath, int iDebug)
  141. {
  142. assert (pszFilePath);
  143. if (!m_pSlm->Load (pszFilePath, true))
  144. {
  145. if (iDebug)
  146. {
  147. fprintf (stderr, "BackEnd: can't load table file %s\n", pszFilePath);
  148. }
  149. return 0;
  150. }
  151. m_pTips->Init(m_pSlm->GetSampFormat(), m_pSlm->GetSampFreq());
  152. m_iSynthBuffSamples = SYNTH_PROPORTION * m_pSlm->GetSampFreq();
  153. if ((m_pnSynthBuff = new short[m_iSynthBuffSamples]) == NULL)
  154. {
  155. return 0;
  156. }
  157. return 1;
  158. }
  159. /*****************************************************************************
  160. * CBEndImp::SetGain *
  161. *-------------------*
  162. * Description:
  163. *
  164. ******************************************************************* PACOG ***/
  165. void CBEndImp::SetGain (double dGain)
  166. {
  167. m_pTips->SetGain(dGain);
  168. }
  169. /*****************************************************************************
  170. * CBEndImp::GetSampFreq *
  171. *-----------------------*
  172. * Description:
  173. *
  174. ******************************************************************* PACOG ***/
  175. int CBEndImp::GetSampFreq ()
  176. {
  177. return m_pSlm->GetSampFreq();
  178. }
  179. /*****************************************************************************
  180. * CBEndImp::GetSpeakerInfo *
  181. *--------------------------*
  182. * Description:
  183. *
  184. ******************************************************************* PACOG ***/
  185. void CBEndImp::GetSpeakerInfo (int* piBaseLine, int* piRefLine, int* piTopLine)
  186. {
  187. m_pSlm->GetTtpParam (piBaseLine, piRefLine, piTopLine);
  188. }
  189. /*****************************************************************************
  190. * CBEndImp::GetPhoneSetFlag *
  191. *--------------------------*
  192. * Description:
  193. *
  194. ******************************************************************* mplumpe ***/
  195. bool CBEndImp::GetPhoneSetFlag ()
  196. {
  197. return m_pSlm->GetPhoneSetFlag ();
  198. }
  199. /*****************************************************************************
  200. * CBEndImp::SetF0SampFreq *
  201. *-------------------------*
  202. * Description:
  203. *
  204. ******************************************************************* PACOG ***/
  205. void CBEndImp::SetF0SampFreq(int iF0SampFreq)
  206. {
  207. assert (iF0SampFreq>0);
  208. m_iF0SampFreq = iF0SampFreq;
  209. }
  210. /*****************************************************************************
  211. * CBEndImp::NewPhoneString *
  212. *--------------------------*
  213. * Description:
  214. *
  215. ******************************************************************* PACOG ***/
  216. int CBEndImp::NewPhoneString (Phone* phList, int nPh, float* newF0, int nNewF0)
  217. {
  218. assert (nPh==0 || phList!=NULL);
  219. assert (nNewF0==0 || newF0!=NULL);
  220. int nF0 = 0;
  221. m_iCurrUnit = 0;
  222. if (( m_iNumUnits = m_pSlm->Process (phList, nPh, 0.0)) == 0)
  223. {
  224. return 0;
  225. }
  226. if ( m_pSlm->GetSynthMethod() )
  227. {
  228. m_pSlm->GetNewF0 ( &m_pflF0, &nF0, m_iF0SampFreq);
  229. m_pTips->NewSentence (m_pflF0, nF0, m_iF0SampFreq);
  230. }
  231. else
  232. {
  233. m_pTips->NewSentence (newF0, nNewF0, m_iF0SampFreq);
  234. }
  235. return 1;
  236. }
  237. /*****************************************************************************
  238. * CBEndImp::OutputPending *
  239. *-------------------------*
  240. * Description:
  241. *
  242. ******************************************************************* PACOG ***/
  243. int CBEndImp::OutputPending ()
  244. {
  245. return (m_iNumUnits - m_iCurrUnit) || m_pTips->Pending() || m_iOverflowCurSamples;
  246. }
  247. /*****************************************************************************
  248. * CBEndImp::GenerateOutput *
  249. *--------------------------*
  250. * Description:
  251. *
  252. ******************************************************************* PACOG ***/
  253. int CBEndImp::GenerateOutput (short** ppnSamples, int* piNumSamples)
  254. {
  255. bool fDone = false;
  256. short* pnCurSamples = NULL;
  257. int iNumCurSamples = 0;
  258. assert (ppnSamples && piNumSamples && m_pnSynthBuff);
  259. if ( m_iOverflowCurSamples )
  260. {
  261. assert( m_pnOverflow );
  262. memcpy(m_pnSynthBuff, m_pnOverflow, m_iOverflowCurSamples * sizeof(short));
  263. m_iPrevSamples = m_iOverflowCurSamples;
  264. m_iOverflowCurSamples = 0;
  265. }
  266. do
  267. {
  268. while ( m_pTips->Pending() )
  269. {
  270. if (m_pTips->NextPeriod( &pnCurSamples, &iNumCurSamples))
  271. {
  272. if ( m_iPrevSamples + iNumCurSamples <= m_iSynthBuffSamples )
  273. {
  274. memcpy(&m_pnSynthBuff[m_iPrevSamples], pnCurSamples, iNumCurSamples * sizeof(short));
  275. m_iPrevSamples += iNumCurSamples;
  276. }
  277. else
  278. {
  279. // something's wrong if a single period exceeds the buffer.
  280. assert (iNumCurSamples <= m_iSynthBuffSamples);
  281. // is the overflow buffer too small?
  282. if ( m_iOverflowMaxSamples < iNumCurSamples )
  283. {
  284. if ( m_pnOverflow )
  285. {
  286. delete [] m_pnOverflow;
  287. m_pnOverflow = NULL;
  288. }
  289. if ( (m_pnOverflow = new short[iNumCurSamples]) == NULL )
  290. {
  291. return 0;
  292. }
  293. m_iOverflowMaxSamples = iNumCurSamples;
  294. }
  295. // save the extra in the overflow buffer
  296. memcpy(m_pnOverflow, pnCurSamples, iNumCurSamples * sizeof(short));
  297. m_iOverflowCurSamples = iNumCurSamples;
  298. fDone = true;
  299. break;
  300. }
  301. }
  302. }
  303. if (!fDone)
  304. {
  305. if (m_iCurrUnit < m_iNumUnits)
  306. {
  307. if (! m_pTips->NewUnit (m_pSlm->GetUnit (m_iCurrUnit)))
  308. {
  309. return 0;
  310. }
  311. m_iCurrUnit ++;
  312. }
  313. else
  314. {
  315. *ppnSamples = 0;
  316. *piNumSamples = 0;
  317. fDone = true;
  318. }
  319. }
  320. } while (! fDone);
  321. if ( m_iPrevSamples )
  322. {
  323. *ppnSamples = m_pnSynthBuff;
  324. *piNumSamples = m_iPrevSamples;
  325. m_iPrevSamples = 0;
  326. }
  327. else
  328. {
  329. *ppnSamples = 0;
  330. *piNumSamples = 0;
  331. }
  332. return 1;
  333. }
  334. /*****************************************************************************
  335. * CBEndImp::GetChunk *
  336. *--------------------*
  337. * Description:
  338. *
  339. ******************************************************************* PACOG ***/
  340. int CBEndImp::GetChunk(ChkDescript** ppChunk)
  341. {
  342. assert (ppChunk);
  343. if (!ppChunk)
  344. {
  345. return 0;
  346. }
  347. if (m_iNumUnits > 0)
  348. {
  349. if (m_iCurrUnit < m_iNumUnits)
  350. {
  351. *ppChunk = m_pSlm->GetChunk (m_iCurrUnit++);
  352. }
  353. }
  354. return 1;
  355. }