NoteLabeler.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. /* ----------------------------------------------------------------- */
  2. /* The HMM-Based Singing Voice Synthesis System "Sinsy" */
  3. /* developed by Sinsy Working Group */
  4. /* http://sinsy.sourceforge.net/ */
  5. /* ----------------------------------------------------------------- */
  6. /* */
  7. /* Copyright (c) 2009-2015 Nagoya Institute of Technology */
  8. /* Department of Computer Science */
  9. /* */
  10. /* All rights reserved. */
  11. /* */
  12. /* Redistribution and use in source and binary forms, with or */
  13. /* without modification, are permitted provided that the following */
  14. /* conditions are met: */
  15. /* */
  16. /* - Redistributions of source code must retain the above copyright */
  17. /* notice, this list of conditions and the following disclaimer. */
  18. /* - Redistributions in binary form must reproduce the above */
  19. /* copyright notice, this list of conditions and the following */
  20. /* disclaimer in the documentation and/or other materials provided */
  21. /* with the distribution. */
  22. /* - Neither the name of the Sinsy working group nor the names of */
  23. /* its contributors may be used to endorse or promote products */
  24. /* derived from this software without specific prior written */
  25. /* permission. */
  26. /* */
  27. /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
  28. /* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
  29. /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
  30. /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
  31. /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */
  32. /* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */
  33. /* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
  34. /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
  35. /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
  36. /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
  37. /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY */
  38. /* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
  39. /* POSSIBILITY OF SUCH DAMAGE. */
  40. /* ----------------------------------------------------------------- */
  41. #include <algorithm>
  42. #include <stdexcept>
  43. #include <sstream>
  44. #include "util_log.h"
  45. #include "NoteLabeler.h"
  46. #include "SyllableLabeler.h"
  47. #include "PhonemeLabeler.h"
  48. #include "util_converter.h"
  49. #include "Deleter.h"
  50. #include "NoteGroup.h"
  51. #include "LabelMeasure.h"
  52. #include "ScorePosition.h"
  53. namespace sinsy
  54. {
  55. namespace
  56. {
  57. /*!
  58. calculate difference of pitches
  59. */
  60. int calcPitchDifference(const Pitch& p1, const Pitch& p2)
  61. {
  62. int tmp1(p1.getOctave() * 12 + p1.getStep());
  63. int tmp2(p2.getOctave() * 12 + p2.getStep());
  64. return (tmp1 - tmp2);
  65. }
  66. };
  67. /*!
  68. constructor
  69. @param b beat
  70. @param d dynamics
  71. @param k key
  72. */
  73. NoteLabeler::NoteLabeler(const Beat& b, const Dynamics& d, const Key& k) :
  74. prevNote(NULL), nextNote(NULL), beat(b), dynamics(d), key(k),
  75. inSlurFromPrev(false), inSlurToNext(false), pitchDifferenceFromPrev(0), pitchDifferenceToNext(0),
  76. hasPrevPitch(false), hasNextPitch(false), measure(NULL), phrase(NULL),
  77. crescendo(NULL), diminuendo(NULL), prevPhrase(NULL), nextPhrase(NULL)
  78. {
  79. }
  80. /*!
  81. destructor
  82. */
  83. NoteLabeler::~NoteLabeler()
  84. {
  85. std::for_each(children.begin(), children.end(), Deleter<SyllableLabeler>());
  86. std::for_each(dataList.begin(), dataList.end(), Deleter<NoteData>());
  87. }
  88. /*!
  89. is rest or not
  90. */
  91. bool NoteLabeler::isRest() const
  92. {
  93. if (dataList.empty()) {
  94. ERR_MSG("Empty note : " << this);
  95. throw std::runtime_error("NoteLabeler::isRest() dataList is NULL");
  96. }
  97. return dataList.front()->getNote().isRest();
  98. }
  99. /*!
  100. already converted or not
  101. */
  102. bool NoteLabeler::isConverted() const
  103. {
  104. return !children.empty();
  105. }
  106. /*!
  107. @internal
  108. connect lyrics
  109. @return connected lyric
  110. */
  111. std::string NoteLabeler::connectLyrics()
  112. {
  113. if (dataList.empty()) {
  114. return std::string();
  115. }
  116. std::ostringstream oss;
  117. DataList::const_iterator itr(dataList.begin());
  118. DataList::const_iterator itrEnd(dataList.end());
  119. for (; itr != itrEnd; ++itr) {
  120. oss << (*itr)->getNote().getLyric();
  121. }
  122. return oss.str();
  123. }
  124. /*!
  125. get lyric
  126. */
  127. std::string NoteLabeler::getLyric() const
  128. {
  129. if (dataList.empty()) {
  130. throw std::runtime_error("NoteLabeler::getLyric() dataList is empty");
  131. }
  132. return this->lyric;
  133. }
  134. /*!
  135. get syllabic
  136. */
  137. Syllabic NoteLabeler::getSyllabic() const
  138. {
  139. if (dataList.empty()) {
  140. throw std::runtime_error("NoteLabeler::getSyllabic() dataList is empty");
  141. }
  142. Syllabic ret(dataList.front()->getNote().getSyllabic());
  143. const DataList::const_iterator itrEnd(dataList.end());
  144. for (DataList::const_iterator itr(dataList.begin() + 1); itrEnd != itr; ++itr) {
  145. Syllabic syllabic((*itr)->getNote().getSyllabic());
  146. if (Syllabic::BEGIN == syllabic) {
  147. if (Syllabic::END == ret) {
  148. ret = Syllabic::MIDDLE;
  149. } else {
  150. ret = Syllabic::BEGIN;
  151. }
  152. } else if (Syllabic::END == syllabic) {
  153. if (Syllabic::BEGIN == ret) {
  154. ret = Syllabic::SINGLE;
  155. } else {
  156. ret = Syllabic::END;
  157. }
  158. } else if (Syllabic::MIDDLE == syllabic) {
  159. if (Syllabic::SINGLE == ret) {
  160. ret = Syllabic::MIDDLE;
  161. }
  162. }
  163. }
  164. return ret;
  165. }
  166. /*!
  167. get duration
  168. */
  169. size_t NoteLabeler::getDuration() const
  170. {
  171. size_t ret(0);
  172. DataList::const_iterator itr(dataList.begin());
  173. const DataList::const_iterator itrEnd(dataList.end());
  174. for (; itr != itrEnd; ++itr) {
  175. ret += (*itr)->getNote().getDuration();
  176. }
  177. return ret;
  178. }
  179. /*!
  180. add information
  181. @param phonemes phoneme list
  182. @param language language
  183. @param info language dependent information
  184. */
  185. void NoteLabeler::addInfo(const std::vector<PhonemeInfo>& phonemes, const std::string& language, const std::string& info)
  186. {
  187. SyllableLabeler* sLabeler(new SyllableLabeler(language));
  188. sLabeler->setInfo(info);
  189. std::vector<PhonemeInfo>::const_iterator itr(phonemes.begin());
  190. const std::vector<PhonemeInfo>::const_iterator itrEnd(phonemes.end());
  191. for (; itrEnd != itr; ++itr) {
  192. PhonemeLabeler* pLabeler(new PhonemeLabeler(*itr));
  193. sLabeler->addChild(pLabeler);
  194. }
  195. children.push_back(sLabeler);
  196. if (phrase) {
  197. phrase->addSyllableNum(1);
  198. }
  199. if (language.empty() && !this->isRest()) {
  200. if (NULL == measure) {
  201. WARN_MSG("Lyric in unknown language : " << getLyric());
  202. } else {
  203. WARN_MSG("Lyric in unknown language : " << getLyric() << " in measure " << (measure->getIndex() + 1) << "");
  204. }
  205. }
  206. }
  207. /*!
  208. set positions
  209. */
  210. void NoteLabeler::setPositions()
  211. {
  212. const List::iterator itrEnd(children.end());
  213. size_t sz(children.size());
  214. size_t pos(0);
  215. for (List::iterator itr(children.begin()); itrEnd != itr; ++itr) {
  216. (*itr)->setIdxInNote(pos);
  217. ++pos;
  218. (*itr)->setNumInNote(sz);
  219. (*itr)->setPhonemePositions();
  220. }
  221. }
  222. /*!
  223. set label
  224. @param label label
  225. */
  226. void NoteLabeler::setLabel(INoteLabel& label) const
  227. {
  228. if (!isRest()) {
  229. const Note& note(dataList.front()->getNote());
  230. label.setAbsolutePitch(note.getPitch());
  231. Pitch::Step step(note.getPitch().getStep());
  232. if (Mode::MINOR == key.getMode()) {
  233. step += 3;
  234. }
  235. switch (key.getFifths()) {
  236. case 0:
  237. step -= Pitch::C;
  238. break;
  239. case 1:
  240. step -= Pitch::G;
  241. break;
  242. case 2:
  243. step -= Pitch::D;
  244. break;
  245. case 3:
  246. step -= Pitch::A;
  247. break;
  248. case 4:
  249. step -= Pitch::E;
  250. break;
  251. case 5:
  252. step -= Pitch::B;
  253. break;
  254. case 6:
  255. step -= Pitch::Gb;
  256. break;
  257. case 7:
  258. step -= Pitch::Db;
  259. break;
  260. case 8:
  261. step -= Pitch::Ab;
  262. break;
  263. case 9:
  264. step -= Pitch::Eb;
  265. break;
  266. case 10:
  267. step -= Pitch::Bb;
  268. break;
  269. case 11:
  270. step -= Pitch::F;
  271. break;
  272. default :
  273. throw std::runtime_error("NoteLabeler::setLabel() fifths is out of range");
  274. }
  275. while (step < 0) {
  276. step += 12;
  277. }
  278. while (12 <= step) {
  279. step -= 12;
  280. }
  281. label.setRelativePitch(static_cast<size_t>(step));
  282. }
  283. label.setKey(key.getFifths());
  284. label.setBeat(beat);
  285. {
  286. double t = 0.0;
  287. size_t d = 0;
  288. const DataList::const_iterator itrEnd(dataList.end());
  289. for (DataList::const_iterator itr(dataList.begin()); itrEnd != itr; ++itr) {
  290. size_t dur((*itr)->getNote().getDuration());
  291. d += dur;
  292. t += static_cast<double>(dur) / (*itr)->getTempo();
  293. }
  294. label.setTempo(static_cast<double>(d) / t);
  295. }
  296. label.setSyllableNum(children.size());
  297. {
  298. LabelPosition position;
  299. std::for_each(dataList.begin(), dataList.end(), PositionAdder(position));
  300. position.setCount(1);
  301. label.setLength(position);
  302. }
  303. if (measure) {
  304. label.setPositionInMeasure(measureIdx, measure->getMaxPosition());
  305. }
  306. if (phrase) {
  307. label.setPositionInPhrase(phraseIdx, phrase->getPosition());
  308. }
  309. label.setSlurFromPrev(inSlurFromPrev);
  310. label.setSlurToNext(inSlurToNext);
  311. label.setDynamics(dynamics);
  312. if (0 < nextAccent.getCount()) {
  313. label.setLengthToNextAccent(nextAccent);
  314. }
  315. if (0 < prevAccent.getCount()) {
  316. label.setLengthFromPrevAccent(prevAccent);
  317. }
  318. if (0 < nextStaccato.getCount()) {
  319. label.setLengthToNextStaccato(nextStaccato);
  320. }
  321. if (0 < prevStaccato.getCount()) {
  322. label.setLengthFromPrevStaccato(prevStaccato);
  323. }
  324. if (crescendo) {
  325. label.setPositionInCrescendo(crescendoIdx, crescendo->getPosition());
  326. }
  327. if (diminuendo) {
  328. label.setPositionInDiminuendo(diminuendoIdx, diminuendo->getPosition());
  329. }
  330. if (!isRest()) {
  331. if (hasPrevPitch) {
  332. label.setPitchDifferenceFromPrev(pitchDifferenceFromPrev);
  333. }
  334. if (hasNextPitch) {
  335. label.setPitchDifferenceToNext(pitchDifferenceToNext);
  336. }
  337. }
  338. if (prevPhrase) {
  339. label.setPrevPhraseInfo(prevPhrase->getSyllableNum(), prevPhrase->getPosition().getCount());
  340. }
  341. if (phrase) {
  342. label.setPhraseInfo(phrase->getSyllableNum(), phrase->getPosition().getCount());
  343. }
  344. if (nextPhrase) {
  345. label.setNextPhraseInfo(nextPhrase->getSyllableNum(), nextPhrase->getPosition().getCount());
  346. }
  347. }
  348. /*!
  349. add note
  350. @param note note
  351. @param tempo tempo
  352. */
  353. void NoteLabeler::addNote(const Note& note, double tempo)
  354. {
  355. NoteData* data(new NoteData(note, tempo));
  356. dataList.push_back(data);
  357. this->lyric = this->connectLyrics();
  358. // add position (count is 0)
  359. if (measure) {
  360. LabelPosition tmp(note.getDuration(), tempo);
  361. tmp.setCount(0);
  362. measure->addPosition(tmp);
  363. }
  364. }
  365. /*!
  366. get beat
  367. */
  368. const Beat& NoteLabeler::getBeat() const
  369. {
  370. return beat;
  371. }
  372. /*!
  373. get dynamics
  374. */
  375. const Dynamics& NoteLabeler::getDynamics() const
  376. {
  377. return dynamics;
  378. }
  379. /*!
  380. get key
  381. */
  382. const Key& NoteLabeler::getKey() const
  383. {
  384. return key;
  385. }
  386. /*!
  387. set measure
  388. */
  389. void NoteLabeler::setMeasure(LabelMeasure* m)
  390. {
  391. if (NULL != m) {
  392. measureIdx = m->getPosition();
  393. LabelPosition position;
  394. std::for_each(dataList.begin(), dataList.end(), PositionAdder(position));
  395. position.setCount(1);
  396. // add only count
  397. {
  398. LabelPosition tmp;
  399. tmp.setCount(1);
  400. m->addPosition(tmp);
  401. }
  402. } else {
  403. measureIdx = LabelPosition();
  404. }
  405. measure = m;
  406. }
  407. /*!
  408. set phrase
  409. */
  410. void NoteLabeler::setPhrase(NoteGroup* ng)
  411. {
  412. if (NULL != ng) {
  413. phraseIdx = ng->getPosition();
  414. LabelPosition position;
  415. std::for_each(dataList.begin(), dataList.end(), PositionAdder(position));
  416. position.setCount(1);
  417. ng->addPosition(position);
  418. } else {
  419. phraseIdx = LabelPosition();
  420. }
  421. phrase = ng;
  422. }
  423. /*!
  424. set crescendo
  425. */
  426. void NoteLabeler::setCrescendo(NoteGroup* ng)
  427. {
  428. if (NULL != ng) {
  429. crescendoIdx = ng->getPosition();
  430. LabelPosition position;
  431. std::for_each(dataList.begin(), dataList.end(), PositionAdder(position));
  432. position.setCount(1);
  433. ng->addPosition(position);
  434. } else {
  435. crescendoIdx = LabelPosition();
  436. }
  437. crescendo = ng;
  438. }
  439. /*!
  440. set diminuendo
  441. */
  442. void NoteLabeler::setDiminuendo(NoteGroup* ng)
  443. {
  444. if (NULL != ng) {
  445. diminuendoIdx = ng->getPosition();
  446. LabelPosition position;
  447. std::for_each(dataList.begin(), dataList.end(), PositionAdder(position));
  448. position.setCount(1);
  449. ng->addPosition(position);
  450. } else {
  451. diminuendoIdx = LabelPosition();
  452. }
  453. diminuendo = ng;
  454. }
  455. /*!
  456. set previous phrase
  457. */
  458. void NoteLabeler::setPrevPhrase(const NoteGroup* ng)
  459. {
  460. prevPhrase = ng;
  461. }
  462. /*!
  463. set next phrase
  464. */
  465. void NoteLabeler::setNextPhrase(const NoteGroup* ng)
  466. {
  467. nextPhrase = ng;
  468. }
  469. /*!
  470. get phrase
  471. */
  472. const NoteGroup* NoteLabeler::getPhrase() const
  473. {
  474. return phrase;
  475. }
  476. /*!
  477. get pitch
  478. */
  479. Pitch NoteLabeler::getPitch() const
  480. {
  481. if (dataList.empty()) {
  482. ERR_MSG("Empty note : " << this);
  483. throw std::runtime_error("NoteLabeler::getPitch() dataList is NULL");
  484. }
  485. return dataList.front()->getNote().getPitch();
  486. }
  487. /*!
  488. is slur start or not
  489. */
  490. bool NoteLabeler::isSlurStart() const
  491. {
  492. bool ret(false);
  493. DataList::const_iterator itr(dataList.begin());
  494. const DataList::const_iterator itrEnd(dataList.end());
  495. for (; itrEnd != itr; ++itr) {
  496. if ((*itr)->getNote().isSlurStop()) {
  497. ret = false;
  498. }
  499. if ((*itr)->getNote().isSlurStart()) {
  500. ret = true;
  501. }
  502. }
  503. return ret;
  504. }
  505. /*!
  506. is slur stop or not
  507. */
  508. bool NoteLabeler::isSlurStop() const
  509. {
  510. bool ret(false);
  511. DataList::const_iterator itr(dataList.begin());
  512. const DataList::const_iterator itrEnd(dataList.end());
  513. for (; itrEnd != itr; ++itr) {
  514. if ((*itr)->getNote().isSlurStop()) {
  515. ret = true;
  516. }
  517. if ((*itr)->getNote().isSlurStart()) {
  518. ret = false;
  519. }
  520. }
  521. return ret;
  522. }
  523. /*!
  524. set if this note is in slur from previous note or not
  525. */
  526. void NoteLabeler::setInSlurFromPrev(bool b)
  527. {
  528. inSlurFromPrev = b;
  529. }
  530. /*!
  531. set if this note is in slur to next note or not
  532. */
  533. void NoteLabeler::setInSlurToNext(bool b)
  534. {
  535. inSlurToNext = b;
  536. }
  537. /*!
  538. set previous pitch
  539. */
  540. void NoteLabeler::setPrevPitch(const Pitch& p)
  541. {
  542. pitchDifferenceFromPrev = calcPitchDifference(p, getPitch());
  543. hasPrevPitch = true;
  544. }
  545. /*!
  546. set next pitch
  547. */
  548. void NoteLabeler::setNextPitch(const Pitch& p)
  549. {
  550. pitchDifferenceToNext = calcPitchDifference(p, getPitch());
  551. hasNextPitch = true;
  552. }
  553. /*!
  554. get length
  555. */
  556. LabelPosition NoteLabeler::getLength() const
  557. {
  558. LabelPosition ret;
  559. DataList::const_iterator itr(dataList.begin());
  560. const DataList::const_iterator itrEnd(dataList.end());
  561. for (; itrEnd != itr; ++itr) {
  562. ret += (*itr)->getLength();
  563. }
  564. ret.setCount(1);
  565. return ret;
  566. }
  567. /*!
  568. set next accent position
  569. */
  570. void NoteLabeler::setNextAccentPosition(const LabelPosition& p)
  571. {
  572. nextAccent = p;
  573. }
  574. /*!
  575. set previous accent position
  576. */
  577. void NoteLabeler::setPrevAccentPosition(const LabelPosition& p)
  578. {
  579. prevAccent = p;
  580. }
  581. /*!
  582. set next staccato position
  583. */
  584. void NoteLabeler::setNextStaccatoPosition(const LabelPosition& p)
  585. {
  586. nextStaccato = p;
  587. }
  588. /*!
  589. set previous staccato position
  590. */
  591. void NoteLabeler::setPrevStaccatoPosition(const LabelPosition& p)
  592. {
  593. prevStaccato = p;
  594. }
  595. /*!
  596. get number of syllables
  597. */
  598. size_t NoteLabeler::getSyllableNum() const
  599. {
  600. return children.size();
  601. }
  602. /*!
  603. has accent or not
  604. */
  605. bool NoteLabeler::hasAccent() const
  606. {
  607. const DataList::const_iterator itrEnd(dataList.end());
  608. for (DataList::const_iterator itr(dataList.begin()); itrEnd != itr; ++itr) {
  609. if ((*itr)->getNote().hasAccent()) {
  610. return true;
  611. }
  612. }
  613. return false;
  614. }
  615. /*!
  616. has staccato or not
  617. */
  618. bool NoteLabeler::hasStaccato() const
  619. {
  620. const DataList::const_iterator itrEnd(dataList.end());
  621. for (DataList::const_iterator itr(dataList.begin()); itrEnd != itr; ++itr) {
  622. if ((*itr)->getNote().hasStaccato()) {
  623. return true;
  624. }
  625. }
  626. return false;
  627. }
  628. /*!
  629. has breath between this and next notes or not
  630. */
  631. bool NoteLabeler::hasBreathToNext() const
  632. {
  633. const DataList::const_iterator itrEnd(dataList.end());
  634. for (DataList::const_iterator itr(dataList.begin()); itrEnd != itr; ++itr) {
  635. if ((*itr)->getNote().hasBreathMark()) {
  636. return true;
  637. }
  638. }
  639. return false;
  640. }
  641. /*!
  642. set previous note (null -> this is the head note)
  643. */
  644. void NoteLabeler::setPrevNote(const NoteLabeler* prev)
  645. {
  646. this->prevNote = prev;
  647. }
  648. /*!
  649. set next note (null -> this is the tail note)
  650. */
  651. void NoteLabeler::setNextNote(const NoteLabeler* next)
  652. {
  653. this->nextNote = next;
  654. }
  655. /*!
  656. get measure index
  657. */
  658. const LabelPosition& NoteLabeler::getMeasureIdx() const
  659. {
  660. return measureIdx;
  661. }
  662. /*!
  663. set breath phoneme to the tail of the last syllable
  664. */
  665. void NoteLabeler::setBreathPhoneme()
  666. {
  667. if (children.empty()) {
  668. WARN_MSG("Cannot set breath phoneme : no syllables in a note");
  669. return;
  670. }
  671. List::reverse_iterator lastSyllableItr(children.rbegin());
  672. SyllableLabeler::List::const_iterator phonemeItr((*lastSyllableItr)->childBegin());
  673. if ((*lastSyllableItr)->childEnd() == phonemeItr) {
  674. WARN_MSG("Cannot set breath phoneme : no phonemes in a syllable");
  675. return;
  676. }
  677. PhonemeLabeler* br = new PhonemeLabeler(PhonemeInfo(PhonemeInfo::TYPE_BREAK, PhonemeLabeler::BREATH_PHONEME, (*phonemeItr)->getScoreFlag()));
  678. (*lastSyllableItr)->addChild(br);
  679. }
  680. /*!
  681. move to target
  682. */
  683. void NoteLabeler::moveTo(NoteLabeler& target, size_t durationStartIdx)
  684. {
  685. size_t residualSize(0);
  686. size_t totalDuration(0);
  687. const DataList::iterator itrEnd(dataList.end());
  688. for (DataList::iterator itr(dataList.begin()); itrEnd != itr; ++itr) {
  689. size_t dur = (*itr)->getNote().getDuration();
  690. if (durationStartIdx <= totalDuration) { // move
  691. target.addNote((*itr)->getNote(), (*itr)->getTempo());
  692. } else {
  693. ++residualSize;
  694. INT64 diff = static_cast<INT64>(totalDuration + dur) - durationStartIdx;
  695. if (0 < diff) { // cut note and move one-side
  696. (*itr)->note.setDuration(dur - diff);
  697. Note note((*itr)->getNote());
  698. note.setDuration(diff);
  699. target.addNote(note, (*itr)->getTempo());
  700. }
  701. }
  702. totalDuration += dur;
  703. }
  704. // cut
  705. std::for_each(dataList.begin() + residualSize, itrEnd, Deleter<NoteData>());
  706. dataList.resize(residualSize);
  707. }
  708. /*!
  709. get begin iterator of syllables
  710. */
  711. NoteLabeler::List::const_iterator NoteLabeler::childBegin() const
  712. {
  713. return children.begin();
  714. }
  715. /*!
  716. get end iterator of syllables
  717. */
  718. NoteLabeler::List::const_iterator NoteLabeler::childEnd() const
  719. {
  720. return children.end();
  721. }
  722. /*!
  723. constructor
  724. */
  725. NoteLabeler::NoteData::NoteData(const Note& n, double t) : note(n), tempo(t)
  726. {
  727. }
  728. /*!
  729. destructor
  730. */
  731. NoteLabeler::NoteData::~NoteData()
  732. {
  733. }
  734. /*!
  735. get note
  736. */
  737. const Note& NoteLabeler::NoteData::getNote() const
  738. {
  739. return note;
  740. }
  741. /*!
  742. get tempo
  743. */
  744. double NoteLabeler::NoteData::getTempo() const
  745. {
  746. return tempo;
  747. }
  748. /*!
  749. get length
  750. */
  751. LabelPosition NoteLabeler::NoteData::getLength() const
  752. {
  753. LabelPosition ret;
  754. ret.add(note.getDuration(), tempo);
  755. return ret;
  756. }
  757. /*!
  758. constructor
  759. */
  760. NoteLabeler::PositionAdder::PositionAdder(LabelPosition& p) : position(p)
  761. {
  762. }
  763. /*!
  764. copy constructor
  765. */
  766. NoteLabeler::PositionAdder::PositionAdder(const PositionAdder& obj) : position(obj.position)
  767. {
  768. }
  769. /*!
  770. destructor
  771. */
  772. NoteLabeler::PositionAdder::~PositionAdder()
  773. {
  774. }
  775. /*!
  776. ...
  777. */
  778. void NoteLabeler::PositionAdder::operator()(NoteData* data)
  779. {
  780. position.add(data->getNote().getDuration(), data->getTempo());
  781. }
  782. }; // namespace sinsy