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; }
//----------------------------------------------------------------------------- // Test program. // test.exe input.wav outout.wav f0 spec flag // input.wav : argv[1] Input file // output.wav : argv[2] Output file // f0 : argv[3] F0 scaling (a positive number) // spec : argv[4] Formant shift (a positive number) //----------------------------------------------------------------------------- int main(int argc, char *argv[]) { if (argc != 2 && argc != 3 && argc != 4 && argc != 5) { printf("error\n"); return 0; } int fs, nbit, x_length; double *x = wavread(argv[1], &fs, &nbit, &x_length); if (CheckLoadedFile(x, fs, nbit, x_length) == false) { printf("error: File not found.\n"); return 0; } // Allocate memories // The number of samples for F0 int f0_length = GetSamplesForDIO(fs, x_length, FRAMEPERIOD); double *f0 = new double[f0_length]; double *time_axis = new double[f0_length]; // FFT size for CheapTrick int fft_size = GetFFTSizeForCheapTrick(fs); double **spectrogram = new double *[f0_length]; double **aperiodicity = new double *[f0_length]; for (int i = 0; i < f0_length; ++i) { spectrogram[i] = new double[fft_size / 2 + 1]; aperiodicity[i] = new double[fft_size / 2 + 1]; } // F0 estimation F0Estimation(x, x_length, fs, f0_length, f0, time_axis); // Spectral envelope estimation SpectralEnvelopeEstimation(x, x_length, fs, time_axis, f0, f0_length, spectrogram); // Aperiodicity estimation by D4C AperiodicityEstimation(x, x_length, fs, time_axis, f0, f0_length, fft_size, aperiodicity); // Note that F0 must not be changed until all parameters are estimated. ParameterModification(argc, argv, fs, f0, f0_length, spectrogram); // The length of the output waveform int y_length = static_cast<int>((f0_length - 1) * FRAMEPERIOD / 1000.0 * fs) + 1; double *y = new double[y_length]; // Synthesis WaveformSynthesis(f0, f0_length, spectrogram, aperiodicity, fft_size, FRAMEPERIOD, fs, y_length, y); // Output wavwrite(y, y_length, fs, 16, argv[2]); printf("complete.\n"); delete[] x; delete[] time_axis; delete[] f0; delete[] y; for (int i = 0; i < f0_length; ++i) { delete[] spectrogram[i]; delete[] aperiodicity[i]; } delete[] spectrogram; delete[] aperiodicity; return 0; }