//residualSpecgram 波形のコピーが入る。メモリを確保せずに渡す。この関数により必要なメモリが確保される。 //residualSpecgramLength 波形の長さが入る。メモリを確保せずに渡す。この関数により必要なメモリが確保される。 //residualSpecgramIndex 各フレームの波形を指定するインデックスが入る。 //戻り値波形の数(pCount) int pt101(double *x, int xLen, int fs, double *timeAxis, double *f0, double ***residualSpecgram, int **residualSpecgramLength, int *residualSpecgramIndex) { int i, index; double framePeriod = (timeAxis[1]-timeAxis[0])*1000.0; int fftl = (int)pow(2.0, 1.0+(int)(log(3.0*fs/FLOOR_F0+1) / log(2.0))); int tLen = getSamplesForDIO(fs, xLen, framePeriod); int vuvNum; // vuvNum = 0; vuvNum = 1; //tn_fuds for(i = 1;i < tLen;i++) { if(f0[i]!=0.0 && f0[i-1]==0.0) vuvNum++; //無声→有声 if(f0[i]==0.0 && f0[i-1]!=0.0) vuvNum++; //有声→無声 tn_fnds } // vuvNum+=vuvNum-1; // 島数の調整 (有声島と無声島) tn_fnds コメントアウト // if(f0[0] == 0) vuvNum++; tn_fnds コメントアウト // if(f0[tLen-1] == 0) vuvNum++; tn_fnds コメントアウト int stCount, edCount; int *stList, *edList; stList = (int *)malloc(sizeof(int) * vuvNum); edList = (int *)malloc(sizeof(int) * vuvNum); edCount = 0; stList[0] = 0; stCount = 1; index = 1; if(f0[0] != 0) //有声から始まる場合 { for(i = 1;i < tLen;i++) { if(f0[i]==0 && f0[i-1]!=0) //有声→無声 { edList[0] = i-1; edCount++; stList[1] = i; stCount++; index = i; break; //tn_fnds } } } edList[vuvNum-1] = tLen-1; for(i = index;i < tLen;i++) { if(f0[i]!=0.0 && f0[i-1]==0.0) //無声→有声 { edList[edCount++] = i-1; stList[stCount++] = i; } if(f0[i]==0.0 && f0[i-1]!=0.0) //有声→無声 { edList[edCount++] = i-1; stList[stCount++] = i; } } int *wedgeList; wedgeList = (int *)malloc(sizeof(int) * vuvNum); getWedgeList(x, xLen, vuvNum, stList, edList, fs, framePeriod, f0, wedgeList);//島中央のピーク位置を取得 double *signalTime, *f0interpolatedRaw, *totalPhase; double *fixedF0; fixedF0 = (double *)malloc(sizeof(double) * tLen); signalTime = (double *)malloc(sizeof(double) * xLen); f0interpolatedRaw = (double *)malloc(sizeof(double) * xLen); totalPhase = (double *)malloc(sizeof(double) * xLen); for(i = 0;i < tLen;i++) fixedF0[i] = f0[i] == 0 ? DEFAULT_F0 : f0[i]; //F0が0ならデフォルトに補正 for(i = 0;i < xLen;i++) signalTime[i] = (double)i / (double)fs; //サンプル位置の時刻 interp1(timeAxis, fixedF0, tLen, signalTime, xLen, f0interpolatedRaw);//各サンプルのF0 totalPhase[0] = f0interpolatedRaw[0]*2*PI/(double)fs; //各サンプルの位相 for(i = 1;i < xLen;i++) totalPhase[i] = totalPhase[i-1] + f0interpolatedRaw[i]*2*PI/(double)fs; double *pulseLocations; pulseLocations = (double *)malloc(sizeof(double) * xLen); int pCount; pCount = getPulseLocations(x, xLen, totalPhase, vuvNum, stList, edList, fs, framePeriod, wedgeList, pulseLocations);//位相が大きく動くサンプル位置の時刻 //tn_fndsデバッグ //zeroXToFile(x, xLen, f0interpolatedRaw, totalPhase, pCount, pulseLocations, fs, vuvNum, wedgeList); pCount++;//長さ0のダミーパルスを追加 *residualSpecgram = (double **)malloc(sizeof(double *) * pCount); for(i = 0;i < pCount;i++) (*residualSpecgram)[i] = (double *)malloc(sizeof(double) * fftl); *residualSpecgramLength = (int *)malloc(sizeof(int) * pCount); getOnePulseResidualSignal(x, xLen, fs, framePeriod/1000.0, f0, fftl, pulseLocations, pCount, *residualSpecgram, *residualSpecgramLength); getFrameResidualIndex(tLen, pCount, framePeriod/1000, pulseLocations, residualSpecgramIndex); // pulseToFile(pCount, pulseLocations, *residualSpecgramLength); free(fixedF0); free(pulseLocations); free(totalPhase); free(f0interpolatedRaw); free(signalTime); free(wedgeList); free(edList); free(stList); return pCount; }
int main(int argc, char *argv[]) { int i; double *x,*x_cut,*f0,*t,*y; double **residualSpecgram; int fftl; int signalLen; int tLen; int offset,blank; int offsetSample, lengthSample; if(argc < 3) { printf("error: 引数の数が不正です.\n"); return 0; } /* printf("argc:%d\n", argc); for(i = 0;i < argc;i++) printf("%d:%s\n",i, argv[i]); //*/ FILE *fp; int fs, nbit; x = wavread(argv[1], &fs, &nbit, &signalLen); if(x == NULL) { printf("error: 指定されたファイルは存在しません.\n"); return 0; } printf("File information\n"); printf("Sampling : %d Hz %d Bit\n", fs, nbit); printf("Length %d [sample]\n", signalLen); printf("Length %f [sec]\n", (double)signalLen/(double)fs); // Cut x by offset and blank offset = atoi(argv[6]); offsetSample = offset*fs/1000; blank = atoi(argv[9]); if(blank < 0) // 負の場合はoffsetからの距離 { lengthSample = (-blank)*fs/1000; } else { lengthSample = signalLen - offsetSample - (blank*fs/1000); } if (lengthSample <= 0) { printf("Error: offset passes blank\n"); exit(0); } printf ("lengthSample: %d\n",lengthSample); x_cut = (double *)malloc(sizeof(double)*lengthSample); for (i=0; i<lengthSample ; i++) { if (i+offsetSample < signalLen) { x_cut[i] = x[i+offsetSample]; } else { x_cut[i] = 0.0; } } // F0は何サンプル分あるかを事前に計算する. tLen = getSamplesForDIO(fs, lengthSample, FRAMEPERIOD); printf ("tLen: %d\n",tLen); f0 = (double *)malloc(sizeof(double)*tLen); t = (double *)malloc(sizeof(double)*tLen); // f0 estimation by DIO DWORD elapsedTime; printf("\nAnalysis\n"); elapsedTime = timeGetTime(); dio(x_cut, lengthSample, fs, FRAMEPERIOD, t, f0); printf("DIO: %d [msec]\n", timeGetTime() - elapsedTime); fftl = getFFTLengthForStar(fs); residualSpecgram = (double **)malloc(sizeof(double *) * tLen); for(i = 0;i < tLen;i++) residualSpecgram[i] = (double *)malloc(sizeof(double) * (fftl/2+1)); // 非周期性指標の分析 elapsedTime = timeGetTime(); pt100(x_cut, lengthSample, fs, t, f0, residualSpecgram); printf("PLATINUM: %d [msec]\n", timeGetTime() - elapsedTime); // 時間長の伸縮 int lengthMsec, stLengthMsec, inputLengthMsec; double ratio; inputLengthMsec = (int)(tLen*FRAMEPERIOD); lengthMsec = atoi(argv[7]); stLengthMsec = atoi(argv[8]); int loop; loop = (lengthMsec-stLengthMsec)/(inputLengthMsec-stLengthMsec); ratio = (double)(lengthMsec) / (double)(inputLengthMsec - stLengthMsec); // 制御パラメタのメモリ確保 double *fixedF0; double **fixedResidualSpecgram; int tLen2; // tLen2 = (int)(0.5+(double)(lengthMsec+offset)/FRAMEPERIOD); //ここを修正 tLen2 = (int)(0.5+(double)(lengthMsec+stLengthMsec)/FRAMEPERIOD); fixedF0 = (double *) malloc(sizeof(double) * tLen2); fixedResidualSpecgram = (double **)malloc(sizeof(double *) * tLen2); for(i = 0;i < tLen2;i++) fixedResidualSpecgram[i] = (double *)malloc(sizeof(double) * (fftl/2+1)); // 最終波形のメモリ確保 int signalLen2; signalLen2 = (int)((lengthMsec+stLengthMsec)/1000.0*(double)fs); y = (double *)malloc(sizeof(double)*signalLen2); if (!y) { printf ("Error: y malloc() NULL\n"); } for(i = 0;i < signalLen2;i++) y[i] = 0.0; // printf("length:%d, %f\n",signalLen2, (double)signalLen2/(double)fs*1000.0); // printf("%d, %d, %d\n",lengthMsec, offset, fs); // 合成の前にF0の操作 (引数) equalizingPicth(f0, tLen, argv[3], atoi(argv[11]) ); // stretchTime(f0, tLen, fftl, residualSpecgram, // fixedF0, tLen2, fixedResidualSpecgram, stLengthMsec/(int)FRAMEPERIOD, ratio); int st, ed; int tempo; int pitchType; st = stLengthMsec+(inputLengthMsec-stLengthMsec)/3; ed = stLengthMsec+2*(inputLengthMsec-stLengthMsec)/3; tLen2 = stretchTime(f0, tLen, fftl, residualSpecgram, fixedF0, tLen2, fixedResidualSpecgram, st/(int)FRAMEPERIOD, ed/(int)FRAMEPERIOD, loop); pitchType=0; if (argc >= 13 && argv[12][0]=='!') { tempo = atoi(&(argv[12][1])); pitchType=0; } else if (argc >= 13 && strchr(argv[12],'Q') != NULL) { char *c; pitchType=1; c = strchr(argv[12],'Q'); c++; tempo = atoi(c); } else if (argc >= 13) { tempo = atoi(argv[12]); } else { tempo = 120; } printf ("tempo: %d\n",tempo); // ピッチベンドの取得 double *pitchBend=NULL; int bLen=0; if (pitchType==0) { if (argc >= 14) { bLen = getF0Contour(argv[13],NULL); pitchBend = (double *)malloc(sizeof(double) * bLen); bLen = getF0Contour(argv[13], pitchBend); } else { bLen = 3; pitchBend = (double *)malloc(sizeof(double) * bLen); pitchBend[0]=1.0; pitchBend[1]=1.0; pitchBend[2]=1.0; } } else if (pitchType==1) { int i,j; char arg1[100]; bLen = argc - 12; pitchBend = (double *)malloc(sizeof(double) * bLen); for (i=0; i<bLen; i++) { memset(arg1,0,sizeof(arg1)); for (j=0; j+1<sizeof(arg1) && argv[i+12][j] != '\0'; j++) { if (isdigit(argv[i+12][j]) || argv[i+12][j]=='.' || argv[i+12][j]=='+' || argv[i+12][j]=='-') { arg1[j]=argv[i+12][j]; } else { break; } } sscanf(arg1,"%lf",&(pitchBend[i])); pitchBend[i] = pow(2.0, pitchBend[i]/1200.0); } } createFinalPitch2(fixedF0, tLen2, pitchBend, bLen, fs, tempo); // 合成 printf("\nSynthesis\n"); elapsedTime = timeGetTime(); synthesisPt100(fixedF0, tLen2, fixedResidualSpecgram, fftl, FRAMEPERIOD, fs, y, signalLen2); printf("WORLD: %d [msec]\n", timeGetTime() - elapsedTime); // オフセットの設定 //offset = (int)((double)(offset+endOffset)/1000.0*(double)fs); //signalLen2 = (int)((lengthMsec)/1000.0*(double)fs); // signalLen2 -= offset; //for(i = 0;i < signalLen2;i++) y[i] = y[i+offset]; // printf("%d\n", signalLen2); // printf("%f %d\n", (double)signalLen2/(double)fs*1000, offset); // getch(); // ファイルの書き出し (内容には関係ないよ) char header[44]; short *output; double maxAmp; output = (short *)malloc(sizeof(short) * signalLen2); // 振幅の正規化 maxAmp = 0.0; double volume; volume = (double)atoi(argv[10]) / 100.0; printf ("volume: %lf\n",volume); for(i = 0;i < signalLen2;i++) maxAmp = (maxAmp < fabs(y[i])) ? fabs(y[i]) : maxAmp; if (maxAmp<=0.0) maxAmp=1.0; printf ("maxAmp: %lf\n",maxAmp); for(i = 0;i < signalLen2;i++) output[i] = (short)(32768.0*(y[i]*0.5 * volume/maxAmp)); fp = fopen(argv[1], "rb"); fread(header, sizeof(char), 44, fp); fclose(fp); fp = fopen(argv[2],"wb"); fwrite(header, sizeof(char), 44, fp); fwrite(output, sizeof(short), signalLen2, fp); fseek(fp, 40, SEEK_SET); signalLen2*=2; fwrite(&signalLen2, sizeof(int), 1, fp); fclose(fp); free(output); free(pitchBend); free(x); free(t); free(f0); free(fixedF0); free(y); for(i = 0;i < tLen;i++) { free(residualSpecgram[i]); } for(i = 0;i < tLen2;i++) { free(fixedResidualSpecgram[i]); } free(fixedResidualSpecgram); free(residualSpecgram); printf("complete.\n"); return 0; }
void pt100(double *x, int xLen, int fs, double *timeAxis, double *f0, double **residualSpecgram) { int i, j, index; double framePeriod = (timeAxis[1]-timeAxis[0])*1000.0; int fftl = (int)pow(2.0, 1.0+(int)(log(3.0*fs/FLOOR_F0+1) / log(2.0))); int tLen = getSamplesForDIO(fs, xLen, framePeriod); int vuvNum; vuvNum = 0; for(i = 1;i < tLen;i++) { if(f0[i]!=0.0 && f0[i-1]==0.0) vuvNum++; } vuvNum+=vuvNum-1; // 島数の調整 (有声島と無声島) if(f0[0] == 0) vuvNum++; if(f0[tLen-1] == 0) vuvNum++; int stCount, edCount; int *stList, *edList; stList = (int *)malloc(sizeof(int) * vuvNum); edList = (int *)malloc(sizeof(int) * vuvNum); edCount = 0; stList[0] = 0; stCount = 1; index = 1; if(f0[0] != 0) { for(i = 1;i < tLen;i++) { if(f0[i]==0 && f0[i-1]!=0) { edList[0] = i-1; edCount++; stList[1] = i; stCount++; index = i; } } } edList[vuvNum-1] = tLen-1; for(i = index;i < tLen;i++) { if(f0[i]!=0.0 && f0[i-1]==0.0) { edList[edCount++] = i-1; stList[stCount++] = i; } if(f0[i]==0.0 && f0[i-1]!=0.0) { edList[edCount++] = i-1; stList[stCount++] = i; } } int *wedgeList; wedgeList = (int *)malloc(sizeof(int) * vuvNum); getWedgeList(x, xLen, vuvNum, stList, edList, fs, framePeriod, f0, wedgeList);//島中央のピーク位置を取得 double *signalTime, *f0interpolatedRaw, *totalPhase; double *fixedF0; fixedF0 = (double *)malloc(sizeof(double) * tLen); signalTime = (double *)malloc(sizeof(double) * xLen); f0interpolatedRaw = (double *)malloc(sizeof(double) * xLen); totalPhase = (double *)malloc(sizeof(double) * xLen); for(i = 0;i < tLen;i++) fixedF0[i] = f0[i] == 0 ? DEFAULT_F0 : f0[i]; //F0が0ならデフォルトに補正 for(i = 0;i < xLen;i++) signalTime[i] = (double)i / (double)fs; //サンプル位置の時刻 interp1(timeAxis, fixedF0, tLen, signalTime, xLen, f0interpolatedRaw);//各サンプルのF0 totalPhase[0] = f0interpolatedRaw[0]*2*PI/(double)fs; //各サンプルの位相 for(i = 1;i < xLen;i++) totalPhase[i] = totalPhase[i-1] + f0interpolatedRaw[i]*2*PI/(double)fs; double *pulseLocations; pulseLocations = (double *)malloc(sizeof(double) * xLen); int pCount; pCount = getPulseLocations(x, xLen, totalPhase, vuvNum, stList, edList, fs, framePeriod, wedgeList, pulseLocations);//位相が大きく動くサンプル位置の時刻 double *tmpResidualSpec; tmpResidualSpec = (double *)malloc(sizeof(double) * fftl); double currentF0; for(j = 0;j < fftl/2;j++) residualSpecgram[0][j] = 0.0; for(i = 1;i < tLen;i++) { currentF0 = f0[i] <= FLOOR_F0 ? DEFAULT_F0 : f0[i]; //フレームのF0 下限ならデフォルトに補正 getOneFrameResidualSignal(x, xLen, fs, i, framePeriod/1000.0, currentF0, fftl, pulseLocations, pCount, //最も近いパルス?前後1周期分の波形に窓をかけたものを取得 tmpResidualSpec); for(j = 0;j < fftl/2;j++) residualSpecgram[i][j] = tmpResidualSpec[j]; } free(fixedF0); free(tmpResidualSpec); free(pulseLocations); free(totalPhase); free(f0interpolatedRaw); free(signalTime); free(wedgeList); free(edList); free(stList); return; }