dio.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /*
  2. *
  3. * F0 推定法 DIO by M. Morise
  4. *
  5. * dio.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. *
  17. * dio.cpp includes a set of functions
  18. * that supports DIO, f0 estimation algorhythm.
  19. *
  20. */
  21. #include "world.h"
  22. // 内部関数(ユーザは触らないほうが良い)
  23. void rawEventByDio(double boundaryF0, double fs, fftw_complex *xSpec, int xLength, int fftl, double shiftTime, double f0Floor, double f0Ceil, double *timeAxis, int tLen,
  24. double *f0Deviations, double *interpolatedF0);
  25. void zeroCrossingEngine(double *x, int xLen, double fs,
  26. double *eLocations, double *iLocations, double *intervals, int *iLen);
  27. void nuttallWindow(int yLen, double *y);
  28. void postprocessing(double framePeriod, double f0Floor, int candidates, int xLen, int fs,
  29. double **f0Map, double *bestF0, double *f0);
  30. // Calculation of the number of F0 contour
  31. // framePeriod の単位はmsec
  32. int getSamplesForDIO(int fs, int xLen, double framePeriod)
  33. {
  34. return (int)((double)xLen / (double)fs / (framePeriod/1000.0) ) + 1;
  35. }
  36. // F0 calculation by using DIO (Distributed Inline filter Operation)
  37. // x : Input signal whose length is xLen [sample]
  38. // xLen : Length of the input signal.
  39. // f0 : Estimated F0 contour
  40. void dio(double *x, int xLen, int fs, double framePeriod,
  41. double *timeAxis, double *f0)
  42. {
  43. int i,j;
  44. // 初期条件 (改良したい人はここから頑張って)
  45. double f0Floor = 80;
  46. double f0Ceil = 640;
  47. double channelsInOctave = 2;
  48. double targetFs = 4000;
  49. // 基礎パラメタの計算
  50. int decimationRatio = (int)(fs/targetFs);
  51. double fss = (double)fs/(double)decimationRatio;
  52. int nBands = (int)(log((double)f0Ceil/(double)f0Floor)/log(2.0) * channelsInOctave);
  53. // ここも基礎パラメタ
  54. double * boundaryF0List = (double *)malloc(sizeof(double) * (nBands+1));
  55. for(i = 0;i <= nBands;i++)
  56. boundaryF0List[i] = f0Floor*pow(2.0, i/channelsInOctave);
  57. // fft Lengthの計算
  58. int yLen = (1 + (int)(xLen/decimationRatio));
  59. int fftl = (int)pow(2.0, 1.0 + (int)(log((double)yLen +
  60. (double)(4*(int)(1.0 + (double)fs/boundaryF0List[0]/2.0)) ) / log(2.0)));
  61. double *y = (double *)malloc(sizeof(double) * fftl);
  62. // ダウンサンプリング
  63. decimateForF0(x, xLen, y, decimationRatio);
  64. // 直流成分の除去 y = y - mean(y)
  65. double meanY = 0.0;
  66. for(i = 0;i < yLen;i++) meanY += y[i];
  67. meanY /= (double)yLen;
  68. for(i = 0;i < yLen;i++) y[i] -= meanY;
  69. for(i = yLen; i < fftl;i++) y[i] = 0.0;
  70. // 中間データの保存用
  71. int tLen; // F0軌跡のサンプル数
  72. tLen = getSamplesForDIO(fs, xLen, framePeriod); // debug
  73. int lengthInMs = 1 + (int)((double)xLen/(double)fs*1000.0);
  74. double **stabilityMap, ** f0Map; // f0mapに候補が全て入るので,結果に納得できない場合は,f0Mapを直接操作する.
  75. stabilityMap = (double **)malloc(sizeof(double *) * (nBands+1));
  76. f0Map = (double **)malloc(sizeof(double *) * (nBands+1));
  77. for(i = 0;i <= nBands;i++)
  78. {
  79. stabilityMap[i] = (double *)malloc(sizeof(double) * tLen);
  80. f0Map[i] = (double *)malloc(sizeof(double) * tLen);
  81. }
  82. // 波形のスペクトルを事前に計算(ここは高速化の余地有り)
  83. fftw_plan forwardFFT; // FFTセット
  84. fftw_complex *ySpec; // スペクトル
  85. ySpec = (fftw_complex *)malloc(sizeof(fftw_complex) * fftl);
  86. #ifdef STND_MULTI_THREAD
  87. if( hFFTWMutex ){
  88. hFFTWMutex->lock();
  89. }
  90. #endif
  91. forwardFFT = fftw_plan_dft_r2c_1d(fftl, y, ySpec, FFTW_ESTIMATE);
  92. #ifdef STND_MULTI_THREAD
  93. if( hFFTWMutex ){
  94. hFFTWMutex->unlock();
  95. }
  96. #endif
  97. fftw_execute(forwardFFT); // FFTの実行
  98. // temporary values
  99. double * interpolatedF0;
  100. double * f0Deviations;
  101. interpolatedF0 = (double *) malloc(sizeof(double) * lengthInMs);
  102. f0Deviations = (double *) malloc(sizeof(double) * lengthInMs);
  103. for(i = 0;i < tLen;i++)
  104. timeAxis[i] = (double)i * framePeriod/1000.0;
  105. // イベントの計算 (4つのゼロ交差.詳しくは論文にて)
  106. for(i = 0;i <= nBands;i++)
  107. {
  108. rawEventByDio(boundaryF0List[i], fss, ySpec, yLen, fftl, framePeriod/1000.0, f0Floor, f0Ceil, timeAxis, tLen,
  109. f0Deviations, interpolatedF0);
  110. for(j = 0;j < tLen;j++)
  111. {
  112. stabilityMap[i][j] = f0Deviations[j] / (interpolatedF0[j]+0.00000001);
  113. f0Map[i][j] = interpolatedF0[j];
  114. }
  115. }
  116. // ベスト候補の選定 (基本波らしさを使い一意に決める)
  117. double *bestF0;
  118. bestF0 = (double *)malloc(sizeof(double) * tLen);
  119. double tmp;
  120. for(i = 0;i < tLen;i++)
  121. {
  122. tmp = stabilityMap[0][i];
  123. bestF0[i] = f0Map[0][i];
  124. for(j = 1;j <= nBands;j++)
  125. {
  126. if(tmp > stabilityMap[j][i])
  127. {
  128. tmp = stabilityMap[j][i];
  129. bestF0[i] = f0Map[j][i];
  130. }
  131. }
  132. }
  133. // 後処理 (第一候補と候補マップから最適なパスを探す)
  134. postprocessing(framePeriod/1000.0, f0Floor, nBands+1, xLen, fs, f0Map, bestF0, f0);
  135. // お片づけ(メモリの開放)
  136. free(bestF0);
  137. free(interpolatedF0);
  138. free(f0Deviations);
  139. #ifdef STND_MULTI_THREAD
  140. if( hFFTWMutex ){
  141. hFFTWMutex->lock();
  142. }
  143. #endif
  144. fftw_destroy_plan(forwardFFT);
  145. #ifdef STND_MULTI_THREAD
  146. if( hFFTWMutex ){
  147. hFFTWMutex->unlock();
  148. }
  149. #endif
  150. free(ySpec);
  151. for(i = 0;i <= nBands;i++)
  152. {
  153. free(stabilityMap[i]);
  154. free(f0Map[i]);
  155. }
  156. free(stabilityMap);
  157. free(f0Map);
  158. free(boundaryF0List);
  159. free(y);
  160. }
  161. // イベント数があったか判定
  162. // longの範囲を超えてしまったので苦肉の策
  163. int checkEvent(int x)
  164. {
  165. if(x > 0) return 1;
  166. return 0;
  167. }
  168. // 後処理(4ステップ)
  169. void postprocessing(double framePeriod, double f0Floor, int candidates, int xLen, int fs, double **f0Map, double *bestF0,
  170. double *f0)
  171. {
  172. int i, j, k;
  173. int voiceRangeMinimum = (int)(0.5 + 1.0/framePeriod/f0Floor);
  174. int f0Len = (int)((double)xLen / (double)fs / framePeriod) + 1;
  175. // double allowedRange = 0.1; // これは5 msecの基準なのでframePeriodに併せて調整する.
  176. double allowedRange = 0.1 * framePeriod/0.005; // これは5 msecの基準なのでframePeriodに併せて調整する.
  177. // メモリ節約はできるけど,どうせ少量なのでデバッグのしやすさを優先
  178. double *f0Base;
  179. f0Base = (double *)malloc(sizeof(double) * f0Len);
  180. double *f0Step1;
  181. f0Step1 = (double *)malloc(sizeof(double) * f0Len);
  182. double *f0Step2;
  183. f0Step2 = (double *)malloc(sizeof(double) * f0Len);
  184. double *f0Step3;
  185. f0Step3 = (double *)malloc(sizeof(double) * f0Len);
  186. double *f0Step4;
  187. f0Step4 = (double *)malloc(sizeof(double) * f0Len);
  188. // まずは初期化
  189. for(i = 0;i < voiceRangeMinimum;i++) f0Base[i] = 0;
  190. for(;i < f0Len-voiceRangeMinimum;i++) f0Base[i] = bestF0[i];
  191. for(;i < f0Len;i++) f0Base[i] = 0;
  192. for(i = 0;i < f0Len;i++) f0Step1[i] = 0.0;
  193. // 第一のステップ (F0の跳躍防止)
  194. for(i = voiceRangeMinimum;i < f0Len;i++)
  195. if(fabs((f0Base[i]-f0Base[i-1])/(0.00001+f0Base[i]) ) < allowedRange)
  196. f0Step1[i] = f0Base[i];
  197. // 第二のステップ (無声区間の切り離し)
  198. for(i = 0;i < f0Len;i++) f0Step2[i] = f0Step1[i];
  199. for(i = voiceRangeMinimum;i < f0Len;i++)
  200. {
  201. for(j = 0;j < voiceRangeMinimum;j++)
  202. {
  203. if(f0Step1[i-j] == 0)
  204. {
  205. f0Step2[i] = 0.0;
  206. break;
  207. }
  208. }
  209. }
  210. // 島数の検出
  211. int *positiveIndex, *negativeIndex;
  212. positiveIndex = (int *)malloc(sizeof(int) * f0Len);
  213. negativeIndex = (int *)malloc(sizeof(int) * f0Len);
  214. int positiveCount, negativeCount;
  215. positiveCount = negativeCount = 0;
  216. for(i = 1;i < f0Len;i++)
  217. {
  218. if(f0Step2[i] == 0 && f0Step2[i-1] != 0)
  219. negativeIndex[negativeCount++] = i-1;
  220. else if (f0Step2[i-1] == 0 && f0Step2[i] != 0)
  221. positiveIndex[positiveCount++] = i;
  222. }
  223. // ステップ3(前向き補正)
  224. double refValue1, refValue2, bestError, errorValue;
  225. for(i = 0;i < f0Len;i++) f0Step3[i] = f0Step2[i];
  226. for(i = 0;i < negativeCount;i++)
  227. {
  228. for(j = negativeIndex[i];j < f0Len-1;j++)
  229. {
  230. refValue1 = f0Step3[j]*2 - f0Step3[j-1];
  231. refValue2 = f0Step3[j];
  232. // bestError = fabs(refValue - f0Map[0][j+1]);
  233. bestError = min(fabs(refValue1 - f0Map[0][j+1]), fabs(refValue2 - f0Map[0][j+1]));
  234. for(k = 1;k < candidates;k++)
  235. {
  236. // errorValue = fabs(refValue - f0Map[k][j+1]);
  237. errorValue = min(fabs(refValue1 - f0Map[k][j+1]), fabs(refValue2 - f0Map[k][j+1]));
  238. if(errorValue < bestError)
  239. {
  240. bestError = errorValue;
  241. f0Step3[j+1] = f0Map[k][j+1];
  242. }
  243. }
  244. // if(bestError / (refValue+0.0001) > allowedRange)
  245. if(min(bestError / (refValue1+0.0001), bestError / (refValue2+0.0001)) > allowedRange)
  246. {
  247. f0Step3[j+1] = 0.0;
  248. break;
  249. }
  250. if(i != negativeCount && j == positiveIndex[i+1]-1)
  251. {
  252. negativeIndex[j] = j;
  253. break;
  254. }
  255. }
  256. }
  257. // ステップ4(後向き補正)
  258. for(i = 0;i < f0Len;i++) f0Step4[i] = f0Step3[i];
  259. for(i = positiveCount-1;i >= 0;i--)
  260. {
  261. for(j = positiveIndex[i]+1;j > 1;j--)
  262. {
  263. refValue1 = f0Step4[j]*2 - f0Step4[j-1];
  264. refValue2 = f0Step4[j];
  265. // refValue = f0Step4[j]*2 - f0Step4[j+1];
  266. bestError = min(fabs(refValue1 - f0Map[0][j+1]), fabs(refValue2 - f0Map[0][j+1]));
  267. // bestError = fabs(refValue - f0Map[0][j-1]);
  268. for(k = 1;k < candidates;k++)
  269. {
  270. errorValue = min(fabs(refValue1 - f0Map[k][j-1]), fabs(refValue2 - f0Map[k][j-1]));
  271. // errorValue = fabs(refValue - f0Map[k][j-1]);
  272. if(min(bestError / (refValue1+0.0001), bestError / (refValue2+0.0001)) > allowedRange)
  273. // if(errorValue < bestError)
  274. {
  275. bestError = errorValue;
  276. f0Step4[j-1] = f0Map[k][j-1];
  277. }
  278. }
  279. if(min(bestError / (refValue1+0.0001), bestError / (refValue2+0.0001)) > allowedRange)
  280. // if(bestError / (refValue+0.0001) > allowedRange)
  281. {
  282. f0Step4[j-1] = 0.0;
  283. break;
  284. }
  285. if(i != 0 && j == negativeIndex[i-1]+1) break;
  286. }
  287. }
  288. // コピー
  289. for(i = 0;i < f0Len;i++) f0[i] = f0Step4[i];
  290. /* ステップ5は,性能が上がらないので一時的に削除
  291. // ステップ5(孤立島の切り離し 2回目)
  292. int voiceRangeMinimum2 = 2+(int)(voiceRangeMinimum/2);
  293. for(i = 0;i < f0Len;i++) f0[i] = f0Step4[i];
  294. for(i = voiceRangeMinimum2; i < f0Len-voiceRangeMinimum2;i++)
  295. {
  296. for(j = 0;j < voiceRangeMinimum2;j++)
  297. {
  298. if(f0Step4[i-j] == 0)
  299. break;
  300. }
  301. for(k = 0;k < voiceRangeMinimum2;k++)
  302. {
  303. if(f0Step4[i+k] == 0)
  304. break;
  305. }
  306. f0[i] = j != voiceRangeMinimum2 && k != voiceRangeMinimum2 ?
  307. 0 : f0Step4[i];
  308. }
  309. */
  310. // メモリの開放
  311. free(positiveIndex); free(negativeIndex);
  312. free(f0Base);
  313. free(f0Step1); free(f0Step2); free(f0Step3); free(f0Step4);
  314. }
  315. // イベントを計算する内部関数 (内部変数なので引数・戻り値に手加減なし)
  316. void rawEventByDio(double boundaryF0, double fs, fftw_complex *xSpec, int xLength, int fftl, double framePeriod, double f0Floor, double f0Ceil, double *timeAxis, int tLen,
  317. double *f0Deviations, double *interpolatedF0)
  318. {
  319. int i;
  320. int halfAverageLength = (int)(fs / boundaryF0 / 2 + 0.5);
  321. int indexBias = halfAverageLength*2;
  322. double *equivalentFIR;
  323. equivalentFIR = (double *)malloc(sizeof(double) * fftl);
  324. for(i = halfAverageLength*2;i < fftl;i++) equivalentFIR[i] = 0.0;
  325. nuttallWindow(halfAverageLength*4, equivalentFIR);
  326. fftw_plan forwardFFT; // FFTセット
  327. fftw_complex *eSpec; // スペクトル
  328. eSpec = (fftw_complex *)malloc(sizeof(fftw_complex) * fftl);
  329. #ifdef STND_MULTI_THREAD
  330. if( hFFTWMutex ){
  331. hFFTWMutex->lock();
  332. }
  333. #endif
  334. forwardFFT = fftw_plan_dft_r2c_1d(fftl, equivalentFIR, eSpec, FFTW_ESTIMATE);
  335. #ifdef STND_MULTI_THREAD
  336. if( hFFTWMutex ){
  337. hFFTWMutex->unlock();
  338. }
  339. #endif
  340. fftw_execute(forwardFFT); // FFTの実行
  341. // 複素数の掛け算
  342. double tmp;
  343. for(i = 0;i <= fftl-1;i++)
  344. {
  345. tmp = xSpec[i][0]*eSpec[i][0] - xSpec[i][1]*eSpec[i][1];
  346. eSpec[i][1] = xSpec[i][0]*eSpec[i][1] + xSpec[i][1]*eSpec[i][0];
  347. eSpec[i][0] = tmp;
  348. }
  349. // 低域通過フィルタリング
  350. fftw_plan inverseFFT;
  351. #ifdef STND_MULTI_THREAD
  352. if( hFFTWMutex ){
  353. hFFTWMutex->lock();
  354. }
  355. #endif
  356. inverseFFT = fftw_plan_dft_c2r_1d(fftl, eSpec, equivalentFIR, FFTW_ESTIMATE);
  357. #ifdef STND_MULTI_THREAD
  358. if( hFFTWMutex ){
  359. hFFTWMutex->unlock();
  360. }
  361. #endif
  362. fftw_execute(inverseFFT);
  363. // バイアス(低域通過フィルタによる遅延)の除去
  364. for(i = 0;i < xLength;i++) equivalentFIR[i] = equivalentFIR[i+indexBias];
  365. // 4つのゼロ交差(構造体のほうがいいね) e:event, i:interval
  366. double *nELocations, *pELocations, *dnELocations, *dpELocations;
  367. double *nILocations, *pILocations, *dnILocations, *dpILocations;
  368. double *nIntervals, *pIntervals, *dnIntervals, *dpIntervals;
  369. int nLen, pLen, dnLen, dpLen;
  370. nELocations = (double *)malloc(sizeof(double) * xLength); // xLengthはかなりの保険
  371. pELocations = (double *)malloc(sizeof(double) * xLength);
  372. dnELocations = (double *)malloc(sizeof(double) * xLength);
  373. dpELocations = (double *)malloc(sizeof(double) * xLength);
  374. nILocations = (double *)malloc(sizeof(double) * xLength);
  375. pILocations = (double *)malloc(sizeof(double) * xLength);
  376. dnILocations = (double *)malloc(sizeof(double) * xLength);
  377. dpILocations = (double *)malloc(sizeof(double) * xLength);
  378. nIntervals = (double *)malloc(sizeof(double) * xLength);
  379. pIntervals = (double *)malloc(sizeof(double) * xLength);
  380. dnIntervals = (double *)malloc(sizeof(double) * xLength);
  381. dpIntervals = (double *)malloc(sizeof(double) * xLength);
  382. zeroCrossingEngine(equivalentFIR, xLength, fs,
  383. nELocations, nILocations, nIntervals, &nLen);
  384. for(i = 0;i < xLength;i++) equivalentFIR[i] = -equivalentFIR[i];
  385. zeroCrossingEngine(equivalentFIR, xLength, fs,
  386. pELocations, pILocations, pIntervals, &pLen);
  387. for(i = 0;i < xLength-1;i++) equivalentFIR[i] = equivalentFIR[i]-equivalentFIR[i+1];
  388. zeroCrossingEngine(equivalentFIR, xLength-1, fs,
  389. dnELocations, dnILocations, dnIntervals, &dnLen);
  390. for(i = 0;i < xLength-1;i++) equivalentFIR[i] = -equivalentFIR[i];
  391. zeroCrossingEngine(equivalentFIR, xLength-1, fs,
  392. dpELocations, dpILocations, dpIntervals, &dpLen);
  393. int usableChannel;
  394. usableChannel = checkEvent(nLen-2) * checkEvent(pLen-2) *
  395. checkEvent(dnLen-2) * checkEvent(dpLen-2);
  396. double *interpolatedF0Set[4];
  397. if(usableChannel <= 0)
  398. { // ノー候補でフィニッシュです
  399. for(i = 0;i < tLen;i++)
  400. {
  401. f0Deviations[i] = 100000.0;
  402. interpolatedF0[i] = 0.0;
  403. }
  404. }
  405. else
  406. {
  407. for(i = 0;i < 4;i++)
  408. interpolatedF0Set[i] = (double *)malloc(sizeof(double) * tLen);
  409. // 4つのゼロ交差
  410. interp1(nILocations , nIntervals , nLen , timeAxis, tLen, interpolatedF0Set[0]);
  411. interp1(pILocations , pIntervals , pLen , timeAxis, tLen, interpolatedF0Set[1]);
  412. interp1(dnILocations, dnIntervals, dnLen, timeAxis, tLen, interpolatedF0Set[2]);
  413. interp1(dpILocations, dpIntervals, dpLen, timeAxis, tLen, interpolatedF0Set[3]);
  414. for(i = 0;i < tLen;i++)
  415. {
  416. interpolatedF0[i] = (interpolatedF0Set[0][i] + interpolatedF0Set[1][i] +
  417. interpolatedF0Set[2][i] + interpolatedF0Set[3][i]) / 4.0;
  418. f0Deviations[i] = sqrt( ((interpolatedF0Set[0][i]-interpolatedF0[i])*(interpolatedF0Set[0][i]-interpolatedF0[i])
  419. + (interpolatedF0Set[1][i]-interpolatedF0[i])*(interpolatedF0Set[1][i]-interpolatedF0[i])
  420. + (interpolatedF0Set[2][i]-interpolatedF0[i])*(interpolatedF0Set[2][i]-interpolatedF0[i])
  421. + (interpolatedF0Set[3][i]-interpolatedF0[i])*(interpolatedF0Set[3][i]-interpolatedF0[i])) / 3.0);
  422. if(interpolatedF0[i] > boundaryF0 || interpolatedF0[i] < boundaryF0/2.0
  423. || interpolatedF0[i] > f0Ceil || interpolatedF0[i] < FLOOR) // 70 Hz以下はF0としない.
  424. {
  425. interpolatedF0[i] = 0.0;
  426. f0Deviations[i] = 100000.0;
  427. }
  428. }
  429. for(i = 0;i < 4;i++) free(interpolatedF0Set[i]);
  430. }
  431. // メモリの開放
  432. free(nELocations);
  433. free(pELocations);
  434. free(dnELocations);
  435. free(dpELocations);
  436. free(nILocations);
  437. free(pILocations);
  438. free(dnILocations);
  439. free(dpILocations);
  440. free(nIntervals);
  441. free(pIntervals);
  442. free(dnIntervals);
  443. free(dpIntervals);
  444. #ifdef STND_MULTI_THREAD
  445. if( hFFTWMutex ){
  446. hFFTWMutex->lock();
  447. }
  448. #endif
  449. fftw_destroy_plan(inverseFFT);
  450. fftw_destroy_plan(forwardFFT);
  451. #ifdef STND_MULTI_THREAD
  452. if( hFFTWMutex ){
  453. hFFTWMutex->unlock();
  454. }
  455. #endif
  456. free(eSpec);
  457. free(equivalentFIR);
  458. }
  459. // ゼロ交差を計算
  460. void zeroCrossingEngine(double *x, int xLen, double fs,
  461. double *eLocations, double *iLocations, double *intervals, int *iLen)
  462. {
  463. int i;
  464. int *negativeGoingPoints;
  465. negativeGoingPoints = (int *)malloc(sizeof(int) * xLen);
  466. int tmp1, tmp2;
  467. for(i = 0;i < xLen-1;i++) // 毎回余りを計算するのは無駄
  468. {
  469. tmp1 = x[i]*x[i+1] < 0 ? 1 : 0;
  470. tmp2 = x[i+1] < x[i] ? 1 : 0;
  471. negativeGoingPoints[i] = (i+1) * tmp1 * tmp2;
  472. }
  473. negativeGoingPoints[xLen-1] = 0;
  474. // 有効イベントの検出
  475. int *edges;
  476. edges = (int *)malloc(sizeof(int) * xLen);
  477. int count = 0;
  478. for(i = 0;i < xLen;i++)
  479. {
  480. if(negativeGoingPoints[i] > 0) edges[count++] = negativeGoingPoints[i];
  481. }
  482. // 最終戻り値の計算準備
  483. double *fineEdges;
  484. fineEdges = (double *)malloc(sizeof(double) * count);
  485. for(i = 0;i < count;i++)
  486. {
  487. fineEdges[i] = (double)edges[i] - x[edges[i]-1]/(x[edges[i]]-x[edges[i]-1]);
  488. }
  489. *iLen = count-1;
  490. for(i = 0;i < *iLen;i++)
  491. {
  492. intervals[i] = fs / (fineEdges[i+1] - fineEdges[i]);
  493. iLocations[i] = (fineEdges[i]+fineEdges[i+1])/2.0/fs;
  494. eLocations[i] = fineEdges[i]/fs;
  495. }
  496. if( count <= 0 ) count=1;
  497. eLocations[count-1] = fineEdges[count-1]/fs;
  498. free(fineEdges);
  499. free(edges);
  500. free(negativeGoingPoints);
  501. }
  502. // Calculation of a nuttall window whose length is xLen
  503. void nuttallWindow(int yLen, double *y)
  504. {
  505. int i;
  506. double tmp;
  507. for(i = 0;i < yLen;i++)
  508. {
  509. tmp = ((double)(i+1) - (double)(yLen+1)/2.0) / (double)(yLen+1);
  510. y[i] = 0.355768+0.487396*cos(2*PI*tmp)+0.144232*cos(4*PI*tmp)+0.012604*cos(6*PI*tmp);
  511. }
  512. }