void StarSeemTest::star_external_ffem() { QFETCH(QString, data); AudioBuffer c; QVERIFY2(c.read(data), ("Failed reading test wave; " + data).toUtf8().data()); /*=== WORLD による分析 ===*/ int timeLength = GetSamplesForDIO(c.format().sampleRate(), c.length(), msFramePeriod); int fftLength = GetFFTSizeForStar(c.format().sampleRate()); double *f0 = new double[timeLength]; double *t = new double[timeLength]; double **specgram = new double*[timeLength]; specgram[0] = new double[timeLength * (fftLength / 2 + 1)]; for(int i = 1; i < timeLength; i++) { specgram[i] = specgram[0] + i * (fftLength / 2 + 1); } Dio(c.data()[0], c.length(), c.format().sampleRate(), msFramePeriod, t, f0); Star(c.data()[0], c.length(), c.format().sampleRate(), msFramePeriod, f0, timeLength, specgram); /*=== WORLD による分析ここまで ===*/ /*=== StarSeem による分析 === */ Envelope *e = new Envelope; QVERIFY2(DioFfem().estimate(e, c.data()[0], c.length(), c.format().sampleRate(), msFramePeriod), "Failed dio FFEM"); // Envelope が正しいか確認する for(int i = 0; i < e->size(); i++) { QVERIFY2(e->value(i) == f0[i], "Error; invalid f0 envelope"); } Specgram *testset = new Specgram; QVERIFY2(StarSeem(e).estimate(testset, c.data()[0], c.length(), fftLength, c.format().sampleRate(), msFramePeriod), "Failed STAR SEEM"); /*=== StarSeem による分析ここまで === */ // 比較開始 for(int t = 0; t < timeLength; t++) { for(int f = 0; f <= fftLength / 2; f++) { if(testset->value(t, f) != specgram[t][f]) { QString s; s = "t = " + QString::number(t) + ", f = " + QString::number(f); s += " actual :" + QString::number(testset->value(t, f)) + " , expceted :" + QString::number(specgram[t][f]); // WORLD 自体は同じだから値が全く同じでないとおかしい。 QFAIL(("Error ;" + s).toUtf8().data()); } } } delete[] specgram[0]; delete[] specgram; delete[] t; delete[] f0; }
static void F0Estimation(double *x, int x_length, WorldParameters *world_parameters) { DioOption option = {0}; InitializeDioOption(&option); // Modification of the option // When you You must set the same value. // If a different value is used, you may suffer a fatal error because of a // illegal memory access. option.frame_period = world_parameters->frame_period; // Valuable option.speed represents the ratio for downsampling. // The signal is downsampled to fs / speed Hz. // If you want to obtain the accurate result, speed should be set to 1. option.speed = 1; // You should not set option.f0_floor to under world_kFloorF0. // If you want to analyze such low F0 speech, please change world_kFloorF0. // Processing speed may sacrify, provided that the FFT length changes. option.f0_floor = 71.0; // You can give a positive real number as the threshold. // Most strict value is 0, but almost all results are counted as unvoiced. // The value from 0.02 to 0.2 would be reasonable. option.allowed_range = 0.1; // Parameters setting and memory allocation. world_parameters->f0_length = GetSamplesForDIO(world_parameters->fs, x_length, world_parameters->frame_period); world_parameters->f0 = (double*) malloc(sizeof(double) * (world_parameters->f0_length)); world_parameters->time_axis = (double*) malloc(sizeof(double) * (world_parameters->f0_length)); double *refined_f0 = (double*) malloc(sizeof(double) * (world_parameters->f0_length)); printf("\nAnalysis\n"); DWORD elapsed_time = timeGetTime(); Dio(x, x_length, world_parameters->fs, &option, world_parameters->time_axis, world_parameters->f0); printf("DIO: %d [msec]\n", timeGetTime() - elapsed_time); // StoneMask is carried out to improve the estimation performance. elapsed_time = timeGetTime(); StoneMask(x, x_length, world_parameters->fs, world_parameters->time_axis, world_parameters->f0, world_parameters->f0_length, refined_f0); printf("StoneMask: %d [msec]\n", timeGetTime() - elapsed_time); for (int i = 0; i < world_parameters->f0_length; ++i) world_parameters->f0[i] = refined_f0[i]; if(refined_f0 != NULL) { free(refined_f0); refined_f0 = NULL; } return; }
DLLEXPORT void DioByOptPtr(double *x, int x_length, int fs, const DioOption* option, double *time_axis, double *f0) { Dio(x, x_length, fs, *option, time_axis, f0); }