[vConnect/trunk/stand2.0] 音源に無い音を合成しようとすると落ちるのを修正,処理時間の計算が正しくできない場合があるのを修正
@@ -85,6 +85,9 @@ | ||
85 | 85 | // ポートの再利用をOKにする |
86 | 86 | int on = 1; |
87 | 87 | setsockopt( s[0], SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof( on ) ); |
88 | + // SIGPIPEの発生を回避 | |
89 | + on = 1; | |
90 | + setsockopt( s[0], SOL_SOCKET, SO_NOSIGPIPE, (char *)&on, sizeof( on ) ); | |
88 | 91 | |
89 | 92 | // サーバーのアドレス情報 |
90 | 93 | struct sockaddr_in server_addr; |
@@ -214,9 +217,11 @@ | ||
214 | 217 | |
215 | 218 | sendWave( s[i], wav ); |
216 | 219 | closeSocket( s[i] ); |
217 | - | |
220 | + | |
221 | +#if !defined( _DEBUG ) | |
218 | 222 | remove( txt ); |
219 | 223 | remove( wav ); |
224 | +#endif | |
220 | 225 | |
221 | 226 | status[i] = 0; |
222 | 227 | s[i] = 0; |
@@ -1,8 +1,8 @@ | ||
1 | 1 | /* |
2 | + * vsqPhonemeDB.h | |
3 | + * Copyright (C) 2010- HAL, | |
4 | + * Copyright (C) 2011 kbinani. | |
2 | 5 | * |
3 | - * vsqHandle.cpp | |
4 | - * (c) HAL 2010- | |
5 | - * | |
6 | 6 | * This files is a part of v.Connect. |
7 | 7 | * vsqPhonemeDB inherits utauVoiceDataBase class. |
8 | 8 | * This class reads UTAU oto.ini in vsq meta-text extention. |
@@ -30,7 +30,7 @@ | ||
30 | 30 | } |
31 | 31 | |
32 | 32 | ~vsqPhonemeDB(){ |
33 | - UtauDB::dbClear(); | |
33 | + //UtauDB::dbClear(); | |
34 | 34 | /*for( unsigned int i = 0; i < voiceDBs.size(); i++ ){ |
35 | 35 | SAFE_DELETE( voiceDBs[i] ); |
36 | 36 | } |
@@ -325,6 +325,7 @@ | ||
325 | 325 | dumpEvents(); |
326 | 326 | dumpMapIDs(); |
327 | 327 | dumpMapHandles(); |
328 | + cout << "vsqFileEx::readCore; size=" << size << endl; | |
328 | 329 | #endif |
329 | 330 | |
330 | 331 | return (size > 0); |
@@ -1,7 +1,7 @@ | ||
1 | 1 | /** |
2 | 2 | * vsqFileEx.h |
3 | 3 | * Copyright (C) 2009-2011 HAL, |
4 | - * Copyright (C) 2011 kbinani | |
4 | + * Copyright (C) 2011 kbinani. | |
5 | 5 | */ |
6 | 6 | #ifndef __vsqFileEx_h__ |
7 | 7 | #define __vsqFileEx_h__ |
@@ -129,6 +129,9 @@ | ||
129 | 129 | |
130 | 130 | private: |
131 | 131 | |
132 | +#if defined( _DEBUG ) | |
133 | +public: | |
134 | +#endif | |
132 | 135 | /// <summary> |
133 | 136 | /// eventsの中身をダンプします |
134 | 137 | /// </summary> |
@@ -155,7 +158,8 @@ | ||
155 | 158 | { |
156 | 159 | string s; |
157 | 160 | mb_conv( i->first, s ); |
158 | - cout << s << endl; | |
161 | + vsqEventEx *item = i->second; | |
162 | + cout << s << ":" << item->toString() << endl; | |
159 | 163 | } |
160 | 164 | } |
161 | 165 |
@@ -1,8 +1,8 @@ | ||
1 | 1 | /* |
2 | + * vsqEventEx.h | |
3 | + * Copyright (C) 2010- HAL, | |
4 | + * Copyright (C) 2011 kbinani. | |
2 | 5 | * |
3 | - * vsqEventEx.h | |
4 | - * (c) HAL 2010- | |
5 | - * | |
6 | 6 | * This files is a part of v.Connect. |
7 | 7 | * vsqEventEx contains vsq-event's properties |
8 | 8 | * and some UTAU properties such as preutterance and voice-overlap. |
@@ -44,6 +44,15 @@ | ||
44 | 44 | } |
45 | 45 | //void setParameter( string_t left, string_t right ); |
46 | 46 | |
47 | + string toString() | |
48 | + { | |
49 | + char buff[1024]; | |
50 | + buff[0] = '\n'; | |
51 | + sprintf( buff, "%d", singerIndex ); | |
52 | + string str_buff = buff; | |
53 | + return "{singerIndex=" + str_buff + "}"; | |
54 | + } | |
55 | + | |
47 | 56 | vsqHandle vibratoHandle; |
48 | 57 | vsqHandle lyricHandle; |
49 | 58 | vsqHandle iconHandle; |
@@ -167,12 +167,12 @@ | ||
167 | 167 | if( false == mVsq.read( input, options ) ) |
168 | 168 | { |
169 | 169 | #ifdef _DEBUG |
170 | - cout << " done, failed" << endl; | |
170 | + cout << "vConnect::synthesize; calling vsq.readVsqFile...done, failed"; | |
171 | 171 | #endif |
172 | 172 | return false; |
173 | 173 | } |
174 | 174 | #ifdef _DEBUG |
175 | - cout << " done, successed" << endl; | |
175 | + cout << "vConnect::synthesize; calling vsq.readVsqFile...done, successed"; | |
176 | 176 | #endif |
177 | 177 | |
178 | 178 | // 空のときは空の wave を出力して終了 |
@@ -205,7 +205,12 @@ | ||
205 | 205 | |
206 | 206 | // 準備1.先行発音などパラメータの適用,及びコントロールカーブをフレーム時刻へ変換 |
207 | 207 | this->calculateVsqInfo(); |
208 | - | |
208 | +#if defined( _DEBUG ) | |
209 | + cout << "vConnect::synthesize; calling mVsq.dumpMapIDs..." << endl; | |
210 | + mVsq.dumpMapIDs(); | |
211 | + cout << "vConnect::synthesize; calling mVsq.dumpMapIDs...done" << endl; | |
212 | +#endif | |
213 | + | |
209 | 214 | aperiodicityLength = fftLength = getFFTLengthForStar(fs); |
210 | 215 | |
211 | 216 | // 準備2.合成に必要なローカル変数の初期化 |
@@ -245,7 +250,7 @@ | ||
245 | 250 | printf("begin synthesis..\n"); |
246 | 251 | clock_t cl = clock(); |
247 | 252 | synthesizeFromList(&arg); |
248 | - printf("Done: elapsed time = %f[s] for %f[s]'s synthesis.\n", (double)(clock() - cl) / 1000.0, framePeriod * frameLength / 1000.0); | |
253 | + printf("Done: elapsed time = %f[s] for %f[s]'s synthesis.\n", (double)(clock() - cl) / CLOCKS_PER_SEC, framePeriod * frameLength / 1000.0); | |
249 | 254 | |
250 | 255 | // ファイルに書き下す. |
251 | 256 | waveFileEx waveFile; |
@@ -265,31 +270,37 @@ | ||
265 | 270 | corpusManager::phoneme* vConnect::getPhoneme(string_t lyric, int singerIndex, vector<corpusManager *> *managers) |
266 | 271 | { |
267 | 272 | corpusManager::phoneme *ret = NULL; |
268 | - if(singerIndex < managers->size()) | |
273 | + if( singerIndex < managers->size() ) | |
269 | 274 | { |
270 | - ret = (*managers)[singerIndex]->getPhoneme(lyric); | |
275 | + ret = (*managers)[singerIndex]->getPhoneme( lyric ); | |
271 | 276 | } |
272 | 277 | return ret; |
273 | 278 | } |
274 | 279 | |
275 | -int getFirstItem(vsqEventEx **p1, vsqEventEx **p2, | |
276 | - corpusManager::phoneme **ph1, | |
277 | - corpusManager::phoneme **ph2, | |
278 | - vsqFileEx *vsq, vector<corpusManager *> &managers, int beginFrame) | |
280 | +int getFirstItem( | |
281 | + vsqEventEx **p1, | |
282 | + vsqEventEx **p2, | |
283 | + corpusManager::phoneme **ph1, | |
284 | + corpusManager::phoneme **ph2, | |
285 | + vsqFileEx *vsq, | |
286 | + vector<corpusManager *> &managers, | |
287 | + int beginFrame ) | |
279 | 288 | { |
280 | 289 | int ret = vsq->events.eventList.size(); |
281 | - for(int i = 0; i < vsq->events.eventList.size(); i++) | |
290 | + for( int i = 0; i < vsq->events.eventList.size(); i++ ) | |
282 | 291 | { |
283 | - if(vsq->events.eventList[i]->beginFrame <= beginFrame | |
284 | - && beginFrame < vsq->events.eventList[i]->endFrame) | |
292 | + if( vsq->events.eventList[i]->beginFrame <= beginFrame && | |
293 | + beginFrame < vsq->events.eventList[i]->endFrame ) | |
285 | 294 | { |
286 | 295 | *p1 = vsq->events.eventList[i]; |
287 | 296 | *p2 = (i + 1 < vsq->events.eventList.size()) ? vsq->events.eventList[i+1] : NULL; |
288 | 297 | ret = i; |
289 | - if(*p1) { | |
298 | + if( *p1 ) | |
299 | + { | |
290 | 300 | *ph1 = managers[(*p1)->singerIndex]->getPhoneme((*p1)->lyricHandle.getLyric()); |
291 | 301 | } |
292 | - if(*p2) { | |
302 | + if( *p2 ) | |
303 | + { | |
293 | 304 | *ph2 = managers[(*p2)->singerIndex]->getPhoneme((*p2)->lyricHandle.getLyric()); |
294 | 305 | } |
295 | 306 | break; |
@@ -298,18 +309,21 @@ | ||
298 | 309 | return ret; |
299 | 310 | } |
300 | 311 | |
301 | -int calculateMelCepstrum(float *dst, int fftLength, list<vConnectData *> &frames) | |
312 | +int calculateMelCepstrum( float *dst, int fftLength, list<vConnectData *> &frames ) | |
302 | 313 | { |
303 | 314 | int ret = 0; |
304 | - memset(dst, 0, sizeof(float) * fftLength); | |
305 | - for(list<vConnectData *>::iterator i = frames.begin(); i != frames.end(); i++) { | |
315 | + memset( dst, 0, sizeof( float ) * fftLength ); | |
316 | + list<vConnectData *>::iterator i; | |
317 | + for( i = frames.begin(); i != frames.end(); i++ ) | |
318 | + { | |
306 | 319 | int length; |
307 | 320 | float *data; |
308 | - data = (*i)->phoneme->getMelCepstrum((*i)->index, &length); | |
309 | - for(int j = 0; j < length; j++) { | |
321 | + data = (*i)->phoneme->getMelCepstrum( (*i)->index, &length ); | |
322 | + for( int j = 0; j < length; j++ ) | |
323 | + { | |
310 | 324 | dst[j] += (*i)->morphRatio * data[j]; |
311 | 325 | } |
312 | - ret = max(ret, length); | |
326 | + ret = max( ret, length ); | |
313 | 327 | } |
314 | 328 | return ret; |
315 | 329 | } |
@@ -342,7 +356,7 @@ | ||
342 | 356 | |
343 | 357 | __stnd_thread_start_retval __stnd_declspec synthesizeFromList( void *arg ) |
344 | 358 | { |
345 | - vConnectArg *p = (vConnectArg*)arg; | |
359 | + vConnectArg *p = (vConnectArg *)arg; | |
346 | 360 | |
347 | 361 | // 波形の復元時に FFTW を使う上で必要なメモリの確保. |
348 | 362 | fftw_complex *spectrum = new fftw_complex[p->fftLength]; |
@@ -355,28 +369,37 @@ | ||
355 | 369 | |
356 | 370 | // この処理はスレッドセーフでない. |
357 | 371 | #ifdef STND_MULTI_THREAD |
358 | - if(hMutex) { | |
359 | - stnd_mutex_lock(hMutex); | |
372 | + if( hMutex ) | |
373 | + { | |
374 | + stnd_mutex_lock( hMutex ); | |
360 | 375 | } |
361 | 376 | #endif |
362 | - fftw_plan forward = fftw_plan_dft_1d(p->fftLength, spectrum, cepstrum, FFTW_FORWARD, FFTW_ESTIMATE); | |
377 | + fftw_plan forward = fftw_plan_dft_1d( p->fftLength, spectrum, cepstrum, FFTW_FORWARD, FFTW_ESTIMATE); | |
363 | 378 | fftw_plan forward_r2c = fftw_plan_dft_r2c_1d(p->fftLength, starSpec, residual, FFTW_ESTIMATE); |
364 | 379 | fftw_plan inverse = fftw_plan_dft_1d(p->fftLength, cepstrum, spectrum, FFTW_BACKWARD, FFTW_ESTIMATE); |
365 | 380 | fftw_plan inverse_c2r = fftw_plan_dft_c2r_1d(p->fftLength, spectrum, impulse, FFTW_ESTIMATE); |
366 | 381 | #ifdef STND_MULTI_THREAD |
367 | - if(hMutex) { | |
368 | - stnd_mutex_unlock(hMutex); | |
382 | + if( hMutex ) | |
383 | + { | |
384 | + stnd_mutex_unlock( hMutex ); | |
369 | 385 | } |
370 | 386 | #endif |
371 | 387 | |
372 | 388 | // 検索用ハッシュ |
373 | 389 | map_t<vConnectPhoneme *, OggVorbis_File *> vorbisMap; |
374 | - for(int i = 0; i < p->phonemes->size(); i++) { | |
375 | - if(!(*(p->phonemes))[i]) { continue; } | |
390 | + for( int i = 0; i < p->phonemes->size(); i++ ) | |
391 | + { | |
392 | + if( !(*(p->phonemes))[i] ) | |
393 | + { | |
394 | + continue; | |
395 | + } | |
376 | 396 | OggVorbis_File *ovf = new OggVorbis_File; |
377 | - if((*(p->phonemes))[i]->vorbisOpen(ovf)) { | |
378 | - vorbisMap.insert(make_pair((*(p->phonemes))[i], ovf)); | |
379 | - } else { | |
397 | + if( (*(p->phonemes))[i]->vorbisOpen( ovf ) ) | |
398 | + { | |
399 | + vorbisMap.insert( make_pair( (*(p->phonemes))[i], ovf ) ); | |
400 | + } | |
401 | + else | |
402 | + { | |
380 | 403 | delete ovf; |
381 | 404 | } |
382 | 405 | } |
@@ -386,7 +409,7 @@ | ||
386 | 409 | double currentTime = 0.0, T; |
387 | 410 | |
388 | 411 | // 合成処理 |
389 | - while(currentFrame < p->endFrame) | |
412 | + while( currentFrame < p->endFrame ) | |
390 | 413 | { |
391 | 414 | if(p->f0[currentFrame] < 0) { |
392 | 415 | currentFrame++; |
@@ -397,15 +420,42 @@ | ||
397 | 420 | |
398 | 421 | /* ToDo : MelCepstrum の合成結果を melCepstrum に書き込む. |
399 | 422 | 残差波形の合成結果を starSpec に書き込む. */ |
400 | - cepstrumLength = calculateMelCepstrum(melCepstrum, p->fftLength, (*(p->data))[currentFrame]->dataList); | |
401 | - calculateResidual(starSpec, p->fftLength, (*(p->data))[currentFrame]->dataList, vorbisMap); | |
423 | + list<vConnectData *> *frames = &(*(p->data))[currentFrame]->dataList; | |
424 | + if( NULL == frames ) | |
425 | + { | |
426 | + currentFrame++; | |
427 | + currentTime = (double)currentFrame * framePeriod / 1000.0; | |
428 | + continue; | |
429 | + } | |
430 | + cepstrumLength = | |
431 | + calculateMelCepstrum( melCepstrum, | |
432 | + p->fftLength, | |
433 | + *frames ); | |
434 | + calculateResidual( starSpec, | |
435 | + p->fftLength, | |
436 | + *frames, | |
437 | + vorbisMap ); | |
402 | 438 | |
403 | 439 | // starSpec -> residual DFT を実行する. |
404 | 440 | fftw_execute(forward_r2c); |
405 | 441 | // メルケプストラムをstraSpecに展開. |
406 | - vConnectUtility::extractMelCepstrum(starSpec, p->fftLength, melCepstrum, cepstrumLength, spectrum, impulse, inverse_c2r ,fs); | |
442 | + vConnectUtility::extractMelCepstrum( | |
443 | + starSpec, | |
444 | + p->fftLength, | |
445 | + melCepstrum, | |
446 | + cepstrumLength, | |
447 | + spectrum, | |
448 | + impulse, | |
449 | + inverse_c2r, | |
450 | + fs ); | |
407 | 451 | // 合成パワースペクトルから最小位相応答を計算. |
408 | - getMinimumPhaseSpectrum(starSpec, spectrum, cepstrum, p->fftLength, forward, inverse); | |
452 | + getMinimumPhaseSpectrum( | |
453 | + starSpec, | |
454 | + spectrum, | |
455 | + cepstrum, | |
456 | + p->fftLength, | |
457 | + forward, | |
458 | + inverse ); | |
409 | 459 | |
410 | 460 | // 励起信号スペクトルと周波数領域での掛け算. |
411 | 461 | for(int k = 0; k <= p->fftLength / 2; k++) |
@@ -419,7 +469,8 @@ | ||
419 | 469 | // 実波形に直す. |
420 | 470 | fftw_execute(inverse_c2r); |
421 | 471 | currentPosition = currentTime * fs; |
422 | - for(int k = 0; k < p->fftLength / 2 && currentPosition < p->waveLength; k++, currentPosition++) { | |
472 | + for( int k = 0; k < p->fftLength / 2 && currentPosition < p->waveLength; k++, currentPosition++ ) | |
473 | + { | |
423 | 474 | p->wave[currentPosition] += impulse[k] * p->dynamics[currentFrame]; |
424 | 475 | } |
425 | 476 |
@@ -429,8 +480,9 @@ | ||
429 | 480 | } |
430 | 481 | |
431 | 482 | //================================================================================================= ↓後処理 |
432 | - for(map_t<vConnectPhoneme *, OggVorbis_File*>::iterator i = vorbisMap.begin(); i != vorbisMap.end(); i++) { | |
433 | - ov_clear(i->second); | |
483 | + map_t<vConnectPhoneme *, OggVorbis_File*>::iterator i; | |
484 | + for( i = vorbisMap.begin(); i != vorbisMap.end(); i++) { | |
485 | + ov_clear( i->second ); | |
434 | 486 | delete i->second; |
435 | 487 | } |
436 | 488 |
@@ -443,17 +495,19 @@ | ||
443 | 495 | |
444 | 496 | // この処理はスレッドセーフでない. |
445 | 497 | #ifdef STND_MULTI_THREAD |
446 | - if(hMutex) { | |
447 | - stnd_mutex_lock(hMutex); | |
498 | + if( hMutex ) | |
499 | + { | |
500 | + stnd_mutex_lock( hMutex ); | |
448 | 501 | } |
449 | 502 | #endif |
450 | - fftw_destroy_plan(forward); | |
451 | - fftw_destroy_plan(forward_r2c); | |
452 | - fftw_destroy_plan(inverse); | |
453 | - fftw_destroy_plan(inverse_c2r); | |
503 | + fftw_destroy_plan( forward ); | |
504 | + fftw_destroy_plan( forward_r2c ); | |
505 | + fftw_destroy_plan( inverse ); | |
506 | + fftw_destroy_plan( inverse_c2r ); | |
454 | 507 | #ifdef STND_MULTI_THREAD |
455 | - if(hMutex) { | |
456 | - stnd_mutex_unlock(hMutex); | |
508 | + if( hMutex ) | |
509 | + { | |
510 | + stnd_mutex_unlock( hMutex ); | |
457 | 511 | } |
458 | 512 | #endif |
459 | 513 |
@@ -494,12 +548,14 @@ | ||
494 | 548 | // 自分を消して |
495 | 549 | vector<vsqEventEx*>::iterator it = events->begin(); |
496 | 550 | int j = 0; |
497 | - while( it != events->end() ){ | |
551 | + while( it != events->end() ) | |
552 | + { | |
498 | 553 | if( itemi == (*it) ) break; |
499 | 554 | j++; |
500 | 555 | it++; |
501 | 556 | } |
502 | - if( it != events->end() ){ | |
557 | + if( it != events->end() ) | |
558 | + { | |
503 | 559 | events->erase( it ); |
504 | 560 | SAFE_DELETE( itemi ); |
505 | 561 | } |
@@ -506,7 +562,9 @@ | ||
506 | 562 | |
507 | 563 | // ( i 番目今消しちゃったから次に進んでるのと一緒だから ) |
508 | 564 | if( i >= events->size() ) |
565 | + { | |
509 | 566 | break; |
567 | + } | |
510 | 568 | // 次の音符へ |
511 | 569 | itemi = mVsq.events.eventList[i]; |
512 | 570 | } |