platinum_v4.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. *
  3. * 非周期性成分推定法 PLATINUM 0.0.4 by M. Morise
  4. *
  5. * platinum_v4.cpp
  6. * (c) M. Morise 2010-
  7. * edit and comment by HAL, kbinani
  8. *
  9. * This file is a part of WORLD system.
  10. * WORLD needs FFTW. Please install FFTW to use these files.
  11. * FFTW is here; http://www.fftw.org/
  12. *
  13. * notice: this comment is added by HAL.
  14. * Original files are on the web page below;
  15. * http://www.aspl.is.ritsumei.ac.jp/morise/world/
  16. * (this file is from WORLD 0.0.4
  17. * functions are renamed by HAL to support both 0.0.1 & 0.0.4.)
  18. *
  19. * platinum_v4.cpp includes a set of functions
  20. * that support PLATINUM 0.0.4.
  21. * Notice that aperiodicity of 0.0.1 is much different
  22. * from that of 0.0.4. Please use platinum_v4 function
  23. * for synthesis_v4 function.
  24. *
  25. */
  26. #include "world.h"
  27. #include <stdio.h> // for debug
  28. #include <stdlib.h>
  29. #include <math.h>
  30. void getOneFrameResidualSpec(double *x, int xLen, int fs, int positionIndex, double framePeriod, double f0, double *specgram, int fftl, double *pulseLocations, int pCount,
  31. double *residualSpec, fftw_plan *forwardFFT, fftw_complex *tmpSpec, fftw_complex *starSpec, fftw_complex *ceps, double *tmpWave,
  32. fftw_plan minForward, fftw_plan minInverse)
  33. {
  34. int i;
  35. double T0;
  36. int index, tmpIndex, wLen;
  37. double tmp;
  38. double tmpValue = 100000.0; // safeGuard
  39. for(i = 0;i < pCount;i++)
  40. {
  41. tmp = fabs(pulseLocations[i] - (double)positionIndex*framePeriod);
  42. if(tmp < tmpValue)
  43. {
  44. tmpValue = tmp;
  45. tmpIndex = i;
  46. }
  47. index = 1+(int)(0.5+pulseLocations[tmpIndex]*fs);
  48. }
  49. T0 = (double)fs/f0;
  50. wLen = (int)(0.5 + T0*2.0);
  51. if(wLen+index-(int)(0.5+T0) >= xLen)
  52. {
  53. for(i = 0;i < fftl;i++) tmpWave[i] = 0;
  54. return;
  55. }
  56. for(i = 0;i < wLen;i++)
  57. {
  58. tmpIndex = i+index - (int)(0.5+T0);
  59. tmpWave[i] = x[max(0, tmpIndex)] *
  60. (0.5 - 0.5*cos(2.0*PI*(double)(i+1)/((double)(wLen+1))));
  61. }
  62. for(;i < fftl;i++)
  63. tmpWave[i] = 0.0;
  64. getMinimumPhaseSpectrum(specgram, starSpec, ceps, fftl, minForward, minInverse);
  65. fftw_execute(*forwardFFT);
  66. residualSpec[0] = tmpSpec[0][0]/starSpec[0][0];
  67. for(i = 0;i < fftl/2-1;i++)
  68. {
  69. tmp = starSpec[i+1][0]*starSpec[i+1][0] + starSpec[i+1][1]*starSpec[i+1][1];
  70. residualSpec[i*2+1] = ( starSpec[i+1][0]*tmpSpec[i+1][0] + starSpec[i+1][1]*tmpSpec[i+1][1])/tmp;
  71. residualSpec[i*2+2] = (-starSpec[i+1][1]*tmpSpec[i+1][0] + starSpec[i+1][0]*tmpSpec[i+1][1])/tmp;
  72. }
  73. residualSpec[fftl-1] = tmpSpec[fftl/2][0]/starSpec[fftl/2][0];
  74. }
  75. int getPulseLocations(double *x, int xLen, double *totalPhase, int vuvNum, int *stList, int *edList, int fs, double framePeriod, int *wedgeList, double *pulseLocations)
  76. {
  77. int i, j;
  78. int stIndex, edIndex;
  79. int pCount = 0;
  80. int numberOfLocation;
  81. double *tmpPulseLocations, *basePhase;
  82. tmpPulseLocations = (double *)malloc(sizeof(double) * xLen);
  83. basePhase = (double *)malloc(sizeof(double) * xLen);
  84. double tmp;
  85. for(i = 0;i < vuvNum;i++)
  86. {
  87. stIndex = max(0, (int)((double)fs*(stList[i])*framePeriod/1000.0));
  88. edIndex = min(xLen-1, (int)((double)fs*(edList[i]+1)*framePeriod/1000.0+0.5) -1);
  89. tmp = totalPhase[wedgeList[i]];
  90. for(j = stIndex;j < edIndex-1;j++) basePhase[j] = fmod(totalPhase[j+1]-tmp, 2*PI) - fmod(totalPhase[j]-tmp, 2*PI);
  91. basePhase[0] = 0; numberOfLocation = 0;
  92. for(j = stIndex;j < edIndex;j++)
  93. {
  94. if(fabs(basePhase[j]) > PI/2.0)
  95. {
  96. tmpPulseLocations[numberOfLocation++] = (double)j/(double)fs;
  97. }
  98. }
  99. for(j = 0;j < numberOfLocation;j++) pulseLocations[pCount++] = tmpPulseLocations[j];
  100. }
  101. free(tmpPulseLocations);
  102. free(basePhase);
  103. return pCount;
  104. }
  105. void getWedgeList(double *x, int xLen, int vuvNum, int *stList, int *edList, int fs, double framePeriod, double *f0, int *wedgeList)
  106. {
  107. int i, j;
  108. double LowestF0 = 40.0;
  109. int center, T0;
  110. double peak;
  111. int peakIndex = 0;
  112. double *tmpWav;
  113. double currentF0;
  114. tmpWav = (double *)malloc(sizeof(double) * (int)(fs*2/LowestF0));
  115. for(i = 0;i < vuvNum;i++)
  116. {
  117. center = (int)((stList[i]+edList[i]+1)/2);
  118. currentF0 = f0[center] == 0.0 ? DEFAULT_F0 : f0[center];
  119. T0 = (int)((fs / currentF0)+0.5);
  120. peakIndex = (int)(((1+center)*framePeriod*fs/1000.0)+0.5);
  121. for(j = 0;j < T0*2;j++)
  122. {
  123. // tmpWav[j] = x[peakIndex-T0+j-1];
  124. tmpWav[j] = x[max(0, min(xLen-1, peakIndex-T0+j-1))];
  125. }
  126. peak = 0.0;
  127. peakIndex = 0;
  128. for(j = 0;j < T0*2+1;j++)
  129. {
  130. if(fabs(tmpWav[j]) > peak)
  131. {
  132. peak = tmpWav[j];
  133. peakIndex = j;
  134. }
  135. }
  136. wedgeList[i] = max(0, min(xLen-1, (int)(0.5 + ((center+1)*framePeriod*fs/1000.0)-T0+peakIndex+1.0) - 1));
  137. }
  138. free(tmpWav);
  139. }
  140. // PLATINUM Version 0.0.4. 恐らくこの仕様で確定です.
  141. // Aperiodicity estimation based on PLATINUM
  142. void platinum_v4(double *x, int xLen, int fs, double *timeAxis, double *f0, double **specgram,
  143. double **residualSpecgram)
  144. {
  145. int i, j, index;
  146. double framePeriod = (timeAxis[1]-timeAxis[0])*1000.0;
  147. int fftl = (int)pow(2.0, 1.0+(int)(log(3.0*fs/FLOOR_F0+1) / log(2.0)));
  148. int tLen = getSamplesForDIO(fs, xLen, framePeriod);
  149. int vuvNum;
  150. vuvNum = 0;
  151. for(i = 1;i < tLen;i++)
  152. {
  153. if(f0[i]!=0.0 && f0[i-1]==0.0) vuvNum++;
  154. }
  155. vuvNum+=vuvNum-1; // 島数の調整 (有声島と無声島)
  156. if(f0[0] == 0) vuvNum++;
  157. if(f0[tLen-1] == 0) vuvNum++;
  158. int stCount, edCount;
  159. int *stList, *edList;
  160. stList = (int *)malloc(sizeof(int) * vuvNum);
  161. edList = (int *)malloc(sizeof(int) * vuvNum);
  162. edCount = 0;
  163. stList[0] = 0;
  164. stCount = 1;
  165. index = 1;
  166. if(f0[0] != 0)
  167. {
  168. for(i = 1;i < tLen;i++)
  169. {
  170. if(f0[i]==0 && f0[i-1]!=0)
  171. {
  172. edList[0] = i-1;
  173. edCount++;
  174. stList[1] = i;
  175. stCount++;
  176. index = i;
  177. }
  178. }
  179. }
  180. edList[vuvNum-1] = tLen-1;
  181. for(i = index;i < tLen;i++)
  182. {
  183. if(f0[i]!=0.0 && f0[i-1]==0.0)
  184. {
  185. edList[edCount++] = i-1;
  186. stList[stCount++] = i;
  187. }
  188. if(f0[i]==0.0 && f0[i-1]!=0.0)
  189. {
  190. edList[edCount++] = i-1;
  191. stList[stCount++] = i;
  192. }
  193. }
  194. int *wedgeList;
  195. wedgeList = (int *)malloc(sizeof(int) * vuvNum);
  196. getWedgeList(x, xLen, vuvNum, stList, edList, fs, framePeriod, f0, wedgeList);
  197. double *signalTime, *f0interpolatedRaw, *totalPhase;
  198. double *fixedF0;
  199. fixedF0 = (double *)malloc(sizeof(double) * tLen);
  200. signalTime = (double *)malloc(sizeof(double) * xLen);
  201. f0interpolatedRaw = (double *)malloc(sizeof(double) * xLen);
  202. totalPhase = (double *)malloc(sizeof(double) * xLen);
  203. // マルチスレッド用にこちらに確保.
  204. double *tmpWave;
  205. fftw_plan forwardFFT; // FFTセット
  206. fftw_plan minForward, minInverse;
  207. fftw_complex *tmpSpec, *starSpec, *ceps; // スペクトル
  208. tmpSpec = (fftw_complex *)malloc(sizeof(fftw_complex) * fftl);
  209. starSpec = (fftw_complex *)malloc(sizeof(fftw_complex) * fftl);
  210. ceps = (fftw_complex *)malloc(sizeof(fftw_complex) * fftl);
  211. tmpWave = (double *)malloc(sizeof(double) * fftl);
  212. // Mutex 操作はひとつにまとめる.
  213. #ifdef STND_MULTI_THREAD
  214. if( hFFTWMutex ){
  215. hFFTWMutex->lock();
  216. }
  217. #endif
  218. forwardFFT = fftw_plan_dft_r2c_1d(fftl, tmpWave, tmpSpec, FFTW_ESTIMATE);
  219. minForward = fftw_plan_dft_1d(fftl, starSpec, ceps, FFTW_FORWARD, FFTW_ESTIMATE);
  220. minInverse = fftw_plan_dft_1d(fftl, ceps, starSpec, FFTW_BACKWARD, FFTW_ESTIMATE);
  221. #ifdef STND_MULTI_THREAD
  222. if( hFFTWMutex ){
  223. hFFTWMutex->unlock();
  224. }
  225. #endif
  226. for(i = 0;i < tLen;i++) fixedF0[i] = f0[i] == 0 ? DEFAULT_F0 : f0[i];
  227. for(i = 0;i < xLen;i++) signalTime[i] = (double)i / (double)fs;
  228. interp1(timeAxis, fixedF0, tLen, signalTime, xLen, f0interpolatedRaw);
  229. totalPhase[0] = f0interpolatedRaw[0]*2*PI/(double)fs;
  230. for(i = 1;i < xLen;i++) totalPhase[i] = totalPhase[i-1] + f0interpolatedRaw[i]*2*PI/(double)fs;
  231. double *pulseLocations;
  232. pulseLocations = (double *)malloc(sizeof(double) * xLen);
  233. int pCount;
  234. pCount = getPulseLocations(x, xLen, totalPhase, vuvNum, stList, edList, fs, framePeriod, wedgeList, pulseLocations);
  235. double currentF0;
  236. for(j = 0;j < fftl;j++) residualSpecgram[0][j] = 0.0;
  237. for(i = 1;i < tLen;i++)
  238. {
  239. currentF0 = f0[i] <= FLOOR_F0 ? DEFAULT_F0 : f0[i];
  240. getOneFrameResidualSpec(x, xLen, fs, i, framePeriod/1000.0, currentF0, specgram[i], fftl, pulseLocations, pCount,
  241. residualSpecgram[i], &forwardFFT, tmpSpec, starSpec, ceps, tmpWave, minForward, minInverse);
  242. }
  243. free(fixedF0);
  244. free(pulseLocations);
  245. free(totalPhase); free(f0interpolatedRaw); free(signalTime);
  246. free(wedgeList);
  247. free(edList); free(stList);
  248. #ifdef STND_MULTI_THREAD
  249. if( hFFTWMutex ){
  250. hFFTWMutex->lock();
  251. }
  252. #endif
  253. fftw_destroy_plan(forwardFFT);
  254. fftw_destroy_plan(minForward);
  255. fftw_destroy_plan(minInverse);
  256. #ifdef STND_MULTI_THREAD
  257. if( hFFTWMutex ){
  258. hFFTWMutex->unlock();
  259. }
  260. #endif
  261. free(tmpSpec); free(ceps); free(starSpec);
  262. free(tmpWave);
  263. return;
  264. }