Sinsy.cpp 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  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 <fstream>
  42. #include "sinsy.h"
  43. #include "util_log.h"
  44. #include "Converter.h"
  45. #include "TempScore.h"
  46. #include "XmlReader.h"
  47. #include "XmlWriter.h"
  48. #include "InputFile.h"
  49. #include "OutputFile.h"
  50. #include "WritableStrStream.h"
  51. #ifdef HAVE_HTS
  52. #include "LabelStream.h"
  53. #include "LabelStrings.h"
  54. #include "LabelMaker.h"
  55. #include "HtsEngine.h"
  56. #include "SynthConditionImpl.h"
  57. #endif
  58. #include "ScorePosition.h"
  59. #include "ScoreDoctor.h"
  60. #include "util_score.h"
  61. namespace sinsy
  62. {
  63. namespace
  64. {
  65. const std::string DEFAULT_LANGUAGES = "j";
  66. class ScoreConverter : public IScoreWritable
  67. {
  68. public:
  69. //! constructor
  70. explicit ScoreConverter(IScore& s);
  71. //! destructor
  72. virtual ~ScoreConverter();
  73. //! set encoding
  74. virtual void setEncoding(const std::string& encoding);
  75. //! change tempo
  76. virtual void changeTempo(double tempo);
  77. //! change beat
  78. virtual void changeBeat(const Beat& beat);
  79. //! change dynamics
  80. virtual void changeDynamics(const Dynamics& dynamics);
  81. //! change key
  82. virtual void changeKey(const Key& key);
  83. //! change divisions (duration of a quarter note)
  84. virtual void changeDivisions(size_t d);
  85. //! start crescendo
  86. virtual void startCrescendo();
  87. //! start diminuendo
  88. virtual void startDiminuendo();
  89. //! stop crescendo
  90. virtual void stopCrescendo();
  91. //! stop diminuendo
  92. virtual void stopDiminuendo();
  93. //! add note
  94. virtual void addNote(const Note& note);
  95. private:
  96. //! copy constructor (donot use)
  97. ScoreConverter(const ScoreConverter&);
  98. //! assignment operator (donot use)
  99. ScoreConverter& operator=(const ScoreConverter&);
  100. //! score
  101. IScore& score;
  102. //! divisions
  103. size_t divisions;
  104. };
  105. /*!
  106. constructor
  107. */
  108. ScoreConverter::ScoreConverter(IScore& s) : score(s), divisions(BASE_DIVISIONS)
  109. {
  110. }
  111. /*!
  112. destructor
  113. */
  114. ScoreConverter::~ScoreConverter()
  115. {
  116. }
  117. /*!
  118. set encoding
  119. */
  120. void ScoreConverter::setEncoding(const std::string& encoding)
  121. {
  122. if (!score.setEncoding(encoding)) {
  123. ERR_MSG("Cannot set encoding : " << encoding);
  124. throw std::invalid_argument("ScoreConverter::setEncoding()");
  125. }
  126. }
  127. /*!
  128. change tempo
  129. */
  130. void ScoreConverter::changeTempo(double tempo)
  131. {
  132. if (!score.addTempoMark(tempo)) {
  133. ERR_MSG("Cannot change tempo : " << tempo);
  134. throw std::invalid_argument("ScoreConverter::changeTempo()");
  135. }
  136. }
  137. /*!
  138. change beat
  139. */
  140. void ScoreConverter::changeBeat(const Beat& beat)
  141. {
  142. if (!score.addBeatMark(beat.getBeats(), beat.getBeatType())) {
  143. ERR_MSG("Cannot change beat : " << beat);
  144. throw std::invalid_argument("ScoreConverter::changeBeat()");
  145. }
  146. }
  147. /*!
  148. change dynamics
  149. */
  150. void ScoreConverter::changeDynamics(const Dynamics& dynamics)
  151. {
  152. SuddenDynamicsType d(SUDDENDYNAMICSTYPE_N);
  153. if (dynamics == Dynamics::PPPP) {
  154. d = SUDDENDYNAMICSTYPE_PPPP;
  155. } else if (dynamics == Dynamics::PPP) {
  156. d = SUDDENDYNAMICSTYPE_PPP;
  157. } else if (dynamics == Dynamics::PP) {
  158. d = SUDDENDYNAMICSTYPE_PP;
  159. } else if (dynamics == Dynamics::P) {
  160. d = SUDDENDYNAMICSTYPE_P;
  161. } else if (dynamics == Dynamics::MP) {
  162. d = SUDDENDYNAMICSTYPE_MP;
  163. } else if (dynamics == Dynamics::N) {
  164. d = SUDDENDYNAMICSTYPE_N;
  165. } else if (dynamics == Dynamics::MF) {
  166. d = SUDDENDYNAMICSTYPE_MF;
  167. } else if (dynamics == Dynamics::F) {
  168. d = SUDDENDYNAMICSTYPE_F;
  169. } else if (dynamics == Dynamics::FF) {
  170. d = SUDDENDYNAMICSTYPE_FF;
  171. } else if (dynamics == Dynamics::FFF) {
  172. d = SUDDENDYNAMICSTYPE_FFF;
  173. } else if (dynamics == Dynamics::FFFF) {
  174. d = SUDDENDYNAMICSTYPE_FFFF;
  175. } else { // fail safe
  176. ERR_MSG("Error in API " << FUNC_NAME(dynamics) << " : unknown type");
  177. throw std::invalid_argument("ScoreConverter::changeDynamics() unknown type");
  178. }
  179. if (!score.addSuddenDynamicsMark(d)) {
  180. ERR_MSG("Error in API " << FUNC_NAME(dynamics) << " : Cannot add sudden dynamics mark");
  181. throw std::invalid_argument("ScoreConverter::changeDynamics()");
  182. }
  183. }
  184. /*!
  185. change key
  186. */
  187. void ScoreConverter::changeKey(const Key& key)
  188. {
  189. const Mode& mode(key.getMode());
  190. ModeType m(MODETYPE_MAJOR);
  191. if (mode == Mode::MAJOR) {
  192. m = MODETYPE_MAJOR;
  193. } else if (mode == Mode::MINOR) {
  194. m = MODETYPE_MINOR;
  195. } else { // fail safe
  196. ERR_MSG("Cannot change key : " << key);
  197. throw std::invalid_argument("ScoreConverter::changeKey() unknown mode type");
  198. }
  199. if (!score.addKeyMark(m, key.getFifths())) {
  200. ERR_MSG("Cannot change key : " << key);
  201. throw std::invalid_argument("ScoreConverter::changeKey()");
  202. }
  203. }
  204. /*!
  205. change divisions (duration of a quarter note)
  206. */
  207. void ScoreConverter::changeDivisions(size_t d)
  208. {
  209. if (d <= 0) {
  210. ERR_MSG("Cannot change divisions : " << d);
  211. std::invalid_argument("ScoreConverter::changeDivisions()");
  212. }
  213. divisions = d;
  214. }
  215. /*!
  216. start crescendo
  217. */
  218. void ScoreConverter::startCrescendo()
  219. {
  220. if (!score.addGradualDynamicsMark(GRADUALDYNAMICSTYPE_CRESCENDO_BEGIN)) {
  221. ERR_MSG("Cannot start crescendo");
  222. throw std::invalid_argument("ScoreConverter::startCrescendo()");
  223. }
  224. }
  225. /*!
  226. start diminuendo
  227. */
  228. void ScoreConverter::startDiminuendo()
  229. {
  230. if (!score.addGradualDynamicsMark(GRADUALDYNAMICSTYPE_DIMINUENDO_BEGIN)) {
  231. ERR_MSG("Cannot start diminuendo");
  232. throw std::invalid_argument("ScoreConverter::startDiminuendo()");
  233. }
  234. }
  235. /*!
  236. stop crescendo
  237. */
  238. void ScoreConverter::stopCrescendo()
  239. {
  240. if (!score.addGradualDynamicsMark(GRADUALDYNAMICSTYPE_CRESCENDO_END)) {
  241. ERR_MSG("Cannot stop crescendo");
  242. throw std::invalid_argument("ScoreConverter::stopCrescendo()");
  243. }
  244. }
  245. /*!
  246. stop diminuendo
  247. */
  248. void ScoreConverter::stopDiminuendo()
  249. {
  250. if (!score.addGradualDynamicsMark(GRADUALDYNAMICSTYPE_DIMINUENDO_END)) {
  251. ERR_MSG("Cannot stop diminuendo");
  252. throw std::invalid_argument("ScoreConverter::stopDiminuendo()");
  253. }
  254. }
  255. /*!
  256. add note
  257. */
  258. void ScoreConverter::addNote(const Note& note)
  259. {
  260. if (note.isRest()) { // rest
  261. if (!score.addRest(note.getDuration() * BASE_DIVISIONS / divisions)) {
  262. ERR_MSG("Cannot add rest : " << note);
  263. throw std::invalid_argument("ScoreConverter::addNote()");
  264. }
  265. } else { // pitch
  266. Pitch pitch(note.getPitch());
  267. TieType tieType(TIETYPE_NONE);
  268. if (note.isTieStart()) {
  269. tieType = TIETYPE_BEGIN;
  270. } else if (note.isTieStop()) {
  271. tieType = TIETYPE_END;
  272. }
  273. SlurType slurType(SLURTYPE_NONE);
  274. if (note.isSlurStart()) {
  275. slurType = SLURTYPE_BEGIN;
  276. } else if (note.isSlurStop()) {
  277. slurType = SLURTYPE_END;
  278. }
  279. SyllabicType syllabicType(SYLLABICTYPE_SINGLE);
  280. Syllabic syllabic(note.getSyllabic());
  281. if (Syllabic::BEGIN == syllabic) {
  282. syllabicType = SYLLABICTYPE_BEGIN;
  283. } else if (Syllabic::MIDDLE == syllabic) {
  284. syllabicType = SYLLABICTYPE_MIDDLE;
  285. } else if (Syllabic::END == syllabic) {
  286. syllabicType = SYLLABICTYPE_END;
  287. }
  288. if (!score.addNote(note.getDuration() * BASE_DIVISIONS / divisions, note.getLyric(), pitch.getOctave() * 12 + pitch.getStep(), note.hasAccent(), note.hasStaccato(), tieType, slurType, syllabicType, note.hasBreathMark())) {
  289. ERR_MSG("Cannot add note : " << note);
  290. throw std::invalid_argument("ScoreConverter::addNote()");
  291. }
  292. }
  293. }
  294. };
  295. /*!
  296. constructor
  297. */
  298. SynthCondition::SynthCondition() : impl(NULL)
  299. {
  300. #ifdef HAVE_HTS
  301. this->impl = new SynthConditionImpl();
  302. #endif
  303. }
  304. /*!
  305. destructor
  306. */
  307. SynthCondition::~SynthCondition()
  308. {
  309. #ifdef HAVE_HTS
  310. delete this->impl;
  311. #endif
  312. }
  313. /*!
  314. set play flag
  315. */
  316. void SynthCondition::setPlayFlag()
  317. {
  318. #ifdef HAVE_HTS
  319. this->impl->setPlayFlag();
  320. #endif
  321. }
  322. /*!
  323. unset play flag
  324. */
  325. void SynthCondition::unsetPlayFlag()
  326. {
  327. #ifdef HAVE_HTS
  328. this->impl->unsetPlayFlag();
  329. #endif
  330. }
  331. /*!
  332. set save file path
  333. */
  334. void SynthCondition::setSaveFilePath(const std::string& filePath)
  335. {
  336. #ifdef HAVE_HTS
  337. this->impl->setSaveFilePath(filePath);
  338. #endif
  339. }
  340. /*!
  341. unset save file path
  342. */
  343. void SynthCondition::unsetSaveFilePath()
  344. {
  345. #ifdef HAVE_HTS
  346. this->impl->unsetSaveFilePath();
  347. #endif
  348. }
  349. /*!
  350. set waveform buffer
  351. */
  352. void SynthCondition::setWaveformBuffer(std::vector<double>& waveform)
  353. {
  354. #ifdef HAVE_HTS
  355. this->impl->setWaveformBuffer(waveform);
  356. #endif
  357. }
  358. /*!
  359. unset waveform buffer
  360. */
  361. void SynthCondition::unsetWaveformBuffer()
  362. {
  363. #ifdef HAVE_HTS
  364. this->impl->unsetWaveformBuffer();
  365. #endif
  366. }
  367. class SinsyImpl : public IScoreWriter
  368. {
  369. public:
  370. //! constructor
  371. SinsyImpl() {}
  372. //! destructor
  373. virtual ~SinsyImpl() {}
  374. //! set languages
  375. bool setLanguages(const std::string& languages, const std::string& dirPath) {
  376. return converter.setLanguages(languages, dirPath);
  377. }
  378. //! load voice files
  379. bool loadVoices(const std::vector<std::string>& voices) {
  380. #ifdef HAVE_HTS
  381. return engine.load(voices);
  382. #endif
  383. }
  384. //! set encoding
  385. void setEncoding(const std::string& encoding) {
  386. score.setEncoding(encoding);
  387. }
  388. //! add key mark
  389. void changeKey(const Key& key) {
  390. score.changeKey(key);
  391. }
  392. //! change beat : default beat mark is 4/4
  393. void changeBeat(const Beat& beat) {
  394. score.changeBeat(beat);
  395. }
  396. //! change tempo : default tempo is 100bps
  397. void changeTempo(double tempo) {
  398. score.changeTempo(tempo);
  399. }
  400. //! change dynamics (sudden changes)
  401. void changeDynamics(const Dynamics& dynamics) {
  402. score.changeDynamics(dynamics);
  403. }
  404. //! start crescendo
  405. void startCrescendo() {
  406. score.startCrescendo();
  407. }
  408. //! stop crescendo
  409. void stopCrescendo() {
  410. score.stopCrescendo();
  411. }
  412. //! start diminuendo
  413. void startDiminuendo() {
  414. score.startDiminuendo();
  415. }
  416. //! stop diminuendo
  417. void stopDiminuendo() {
  418. score.stopDiminuendo();
  419. }
  420. //! add note to end of score
  421. void addNote(const Note& note) {
  422. score.addNote(note);
  423. }
  424. //! write score to given IScoreWritable object
  425. void write(IScoreWritable& maker) const {
  426. maker << score;
  427. }
  428. #ifdef HAVE_HTS
  429. //! set alpha for synthesis
  430. bool setAlpha(double alpha) {
  431. return engine.setAlpha(alpha);
  432. }
  433. //! set volume for synthesis
  434. bool setVolume(double volume) {
  435. return engine.setVolume(volume);
  436. }
  437. //! set interpolation weight for synthesis
  438. bool setInterpolationWeight(size_t index, double weight) {
  439. return engine.setInterpolationWeight(index, weight);
  440. }
  441. //! synthesize
  442. bool synthesize(SynthConditionImpl& condition) {
  443. LabelMaker labelMaker(converter);
  444. labelMaker << score;
  445. labelMaker.fix();
  446. LabelStrings label;
  447. labelMaker.outputLabel(label, false, 1, 2);
  448. return engine.synthesize(label, condition);
  449. }
  450. //! stop synthesizing
  451. void stop() {
  452. engine.stop();
  453. }
  454. //! reset stop flag
  455. void resetStopFlag() {
  456. engine.resetStopFlag();
  457. }
  458. #endif
  459. //! clear score
  460. void clearScore() {
  461. score.clear();
  462. }
  463. //! load score from MusicXML
  464. bool loadScoreFromMusicXML(InputFile& xml) {
  465. XmlReader xmlReader;
  466. if (!xmlReader.readXml(xml)) {
  467. ERR_MSG("Cannot parse Xml file");
  468. return false;
  469. }
  470. score << xmlReader;
  471. return true;
  472. }
  473. //! save score to MusicXML
  474. bool saveScoreToMusicXML(const std::string& xml, XmlWriter::Clef clef) {
  475. XmlWriter xmlWriter;
  476. xmlWriter.setClef(clef);
  477. xmlWriter << score;
  478. OutputFile outputFile(xml);
  479. if (!outputFile.isValid()) {
  480. ERR_MSG("Cannot open Xml file");
  481. return false;
  482. }
  483. WritableStrStream stream(outputFile);
  484. if (!xmlWriter.writeXml(stream)) {
  485. ERR_MSG("Cannot write Xml file");
  486. return false;
  487. }
  488. return true;
  489. }
  490. private:
  491. //! copy constructor (donot use)
  492. SinsyImpl(const SinsyImpl&);
  493. //! assignment operator (donot use)
  494. SinsyImpl& operator=(const SinsyImpl&);
  495. //! score
  496. ScoreDoctor score;
  497. //! converter
  498. Converter converter;
  499. #ifdef HAVE_HTS
  500. //! hts_engine API
  501. HtsEngine engine;
  502. #endif
  503. };
  504. /*!
  505. constructor
  506. */
  507. Sinsy::Sinsy() : impl(NULL)
  508. {
  509. try {
  510. impl = new SinsyImpl();
  511. } catch (const std::bad_alloc& ex) {
  512. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  513. delete(impl); // fail safe
  514. }
  515. }
  516. /*!
  517. destructor
  518. */
  519. Sinsy::~Sinsy()
  520. {
  521. delete(impl);
  522. }
  523. /*!
  524. set languages
  525. */
  526. bool Sinsy::setLanguages(const std::string& languages, const std::string& dirPath)
  527. {
  528. try {
  529. if (!impl->setLanguages(languages, dirPath)) {
  530. return false;
  531. }
  532. } catch (const std::exception& ex) {
  533. ERR_MSG("Exception in API " << FUNC_NAME(languages << ", " << dirPath) << " : " << ex.what());
  534. return false;
  535. }
  536. return true;
  537. }
  538. /*!
  539. load voices
  540. */
  541. bool Sinsy::loadVoices(const std::vector<std::string>& voices)
  542. {
  543. try {
  544. if (!impl->loadVoices(voices)) {
  545. return false;
  546. }
  547. } catch (const std::exception& ex) {
  548. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  549. return false;
  550. }
  551. return true;
  552. }
  553. /*!
  554. set encoding
  555. */
  556. bool Sinsy::setEncoding(const std::string& encoding)
  557. {
  558. try {
  559. impl->setEncoding(encoding);
  560. } catch (const std::exception& ex) {
  561. ERR_MSG("Exception in API " << FUNC_NAME(encoding) << " : " << ex.what());
  562. return false;
  563. }
  564. return true;
  565. }
  566. /*!
  567. add beat mark
  568. */
  569. bool Sinsy::addBeatMark(size_t beats, size_t beatType)
  570. {
  571. if (0 == beats) {
  572. ERR_MSG("Wrong beats (== 0) in API " << FUNC_NAME(beats << ", " << beatType));
  573. return false;
  574. }
  575. if (0 == beatType) {
  576. ERR_MSG("Wrong beat type (== 0) in API " << FUNC_NAME(beats << ", " << beatType));
  577. return false;
  578. }
  579. try {
  580. impl->changeBeat(Beat(beats, beatType));
  581. } catch (const std::exception& ex) {
  582. ERR_MSG("Exception in API " << FUNC_NAME(beats << ", " << beatType) << " : " << ex.what());
  583. return false;
  584. }
  585. return true;
  586. }
  587. /*!
  588. add tempo mark
  589. */
  590. bool Sinsy::addTempoMark(double tempo)
  591. {
  592. if (tempo <= 0.0) {
  593. return false;
  594. }
  595. try {
  596. impl->changeTempo(tempo);
  597. } catch (const std::exception& ex) {
  598. ERR_MSG("Exception in API " << FUNC_NAME(tempo) << " : " << ex.what());
  599. return false;
  600. }
  601. return true;
  602. }
  603. /*!
  604. add sudden dynamics mark
  605. */
  606. bool Sinsy::addSuddenDynamicsMark(SuddenDynamicsType suddenDynamicsType)
  607. {
  608. try {
  609. switch (suddenDynamicsType) {
  610. case SUDDENDYNAMICSTYPE_PPPP :
  611. impl->changeDynamics(Dynamics::PPPP);
  612. break;
  613. case SUDDENDYNAMICSTYPE_PPP :
  614. impl->changeDynamics(Dynamics::PPP);
  615. break;
  616. case SUDDENDYNAMICSTYPE_PP :
  617. impl->changeDynamics(Dynamics::PP);
  618. break;
  619. case SUDDENDYNAMICSTYPE_P :
  620. impl->changeDynamics(Dynamics::P);
  621. break;
  622. case SUDDENDYNAMICSTYPE_MP :
  623. impl->changeDynamics(Dynamics::MP);
  624. break;
  625. case SUDDENDYNAMICSTYPE_N :
  626. impl->changeDynamics(Dynamics::N);
  627. break;
  628. case SUDDENDYNAMICSTYPE_MF :
  629. impl->changeDynamics(Dynamics::MF);
  630. break;
  631. case SUDDENDYNAMICSTYPE_F :
  632. impl->changeDynamics(Dynamics::F);
  633. break;
  634. case SUDDENDYNAMICSTYPE_FF :
  635. impl->changeDynamics(Dynamics::FF);
  636. break;
  637. case SUDDENDYNAMICSTYPE_FFF :
  638. impl->changeDynamics(Dynamics::FFF);
  639. break;
  640. case SUDDENDYNAMICSTYPE_FFFF :
  641. impl->changeDynamics(Dynamics::FFFF);
  642. break;
  643. default :
  644. ERR_MSG("Unknown sudden dynamics type in API " << FUNC_NAME(suddenDynamicsType));
  645. return false;
  646. }
  647. } catch (const std::exception& ex) {
  648. ERR_MSG("Exception in API " << FUNC_NAME(suddenDynamicsType) << " : " << ex.what());
  649. return false;
  650. }
  651. return true;
  652. }
  653. /*!
  654. add gradual dynamics mark
  655. */
  656. bool Sinsy::addGradualDynamicsMark(GradualDynamicsType gradualDynamicsType)
  657. {
  658. try {
  659. switch (gradualDynamicsType) {
  660. case GRADUALDYNAMICSTYPE_CRESCENDO_BEGIN :
  661. impl->startCrescendo();
  662. break;
  663. case GRADUALDYNAMICSTYPE_CRESCENDO_END :
  664. impl->stopCrescendo();
  665. break;
  666. case GRADUALDYNAMICSTYPE_DIMINUENDO_BEGIN :
  667. impl->startDiminuendo();
  668. break;
  669. case GRADUALDYNAMICSTYPE_DIMINUENDO_END :
  670. impl->stopDiminuendo();
  671. break;
  672. default :
  673. ERR_MSG("Unknown gradual dynamics type in API " << FUNC_NAME(gradualDynamicsType));
  674. return false;
  675. }
  676. } catch (const std::exception& ex) {
  677. ERR_MSG("Exception in API " << FUNC_NAME(gradualDynamicsType) << " : " << ex.what());
  678. return false;
  679. }
  680. return true;
  681. }
  682. /*!
  683. add key mark
  684. */
  685. bool Sinsy::addKeyMark(ModeType modeType, int fifths)
  686. {
  687. try {
  688. Mode mode;
  689. switch (modeType) {
  690. case MODETYPE_MAJOR :
  691. mode = Mode::MAJOR;
  692. break;
  693. case MODETYPE_MINOR :
  694. mode = Mode::MINOR;
  695. break;
  696. default :
  697. ERR_MSG("Unknown mode type in API " << FUNC_NAME(modeType << ", " << fifths));
  698. return false;
  699. }
  700. impl->changeKey(Key(mode, fifths));
  701. } catch (const std::exception& ex) {
  702. ERR_MSG("Exception in API " << FUNC_NAME(modeType << ", " << fifths) << " : " << ex.what());
  703. return false;
  704. }
  705. return true;
  706. }
  707. /*!
  708. add note
  709. */
  710. bool Sinsy::addNote(size_t duration, const std::string& lyric, size_t pitch, bool accent, bool staccato, TieType tieType, SlurType slurType, SyllabicType syllabicType, bool breath)
  711. {
  712. if (duration <= 0) {
  713. ERR_MSG("Error in API " << FUNC_NAME("") << " : duration(" << duration << ") <= 0");
  714. return false;
  715. }
  716. try {
  717. Note note;
  718. note.setRest(false);
  719. note.setDuration(duration);
  720. note.setLyric(lyric);
  721. note.setPitch(Pitch(pitch % 12, pitch / 12));
  722. note.setAccent(accent);
  723. note.setStaccato(staccato);
  724. note.setBreathMark(breath);
  725. switch (tieType) {
  726. case TIETYPE_NONE :
  727. break;
  728. case TIETYPE_BEGIN :
  729. note.setTieStart(true);
  730. break;
  731. case TIETYPE_END :
  732. note.setTieStop(true);
  733. break;
  734. default :
  735. ERR_MSG("Error in API " << FUNC_NAME("") << " : unknown tie type : " << tieType);
  736. return false;
  737. }
  738. switch (slurType) {
  739. case SLURTYPE_NONE :
  740. break;
  741. case SLURTYPE_BEGIN :
  742. note.setSlurStart(true);
  743. break;
  744. case SLURTYPE_END :
  745. note.setSlurStop(true);
  746. break;
  747. default :
  748. ERR_MSG("Error in API " << FUNC_NAME("") << " : unknown slur type : " << slurType);
  749. return false;
  750. }
  751. switch (syllabicType) {
  752. case SYLLABICTYPE_SINGLE :
  753. note.setSyllabic(Syllabic::SINGLE);
  754. break;
  755. case SYLLABICTYPE_BEGIN :
  756. note.setSyllabic(Syllabic::BEGIN);
  757. break;
  758. case SYLLABICTYPE_MIDDLE :
  759. note.setSyllabic(Syllabic::MIDDLE);
  760. break;
  761. case SYLLABICTYPE_END :
  762. note.setSyllabic(Syllabic::END);
  763. break;
  764. default :
  765. ERR_MSG("Error in API " << FUNC_NAME("") << " : unknown syllabic type : " << syllabicType);
  766. return false;
  767. }
  768. impl->addNote(note);
  769. } catch (const std::exception& ex) {
  770. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  771. return false;
  772. }
  773. return true;
  774. }
  775. /*!
  776. add rest
  777. */
  778. bool Sinsy::addRest(size_t duration)
  779. {
  780. if (duration <= 0) {
  781. ERR_MSG("Error in API " << FUNC_NAME(duration) << " : duration <= 0");
  782. return false;
  783. }
  784. try {
  785. Note note;
  786. note.setRest(true);
  787. note.setDuration(duration);
  788. impl->addNote(note);
  789. } catch (const std::exception& ex) {
  790. ERR_MSG("Exception in API " << FUNC_NAME(duration) << " : " << ex.what());
  791. return false;
  792. }
  793. return true;
  794. }
  795. /*!
  796. push score data to s
  797. */
  798. bool Sinsy::toScore(IScore& s) const
  799. {
  800. try {
  801. ScoreConverter cs(s);
  802. cs << *impl;
  803. } catch (const std::exception& ex) {
  804. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  805. return false;
  806. }
  807. return true;
  808. }
  809. /*!
  810. set alpha
  811. */
  812. bool Sinsy::setAlpha(double alpha)
  813. {
  814. #ifdef HAVE_HTS
  815. return impl->setAlpha(alpha);
  816. #else
  817. return false;
  818. #endif
  819. }
  820. /*!
  821. set volume
  822. */
  823. bool Sinsy::setVolume(double volume)
  824. {
  825. #ifdef HAVE_HTS
  826. return impl->setVolume(volume);
  827. #else
  828. return false;
  829. #endif
  830. }
  831. /*!
  832. set interpolation weight
  833. */
  834. bool Sinsy::setInterpolationWeight(size_t index, double weight)
  835. {
  836. #ifdef HAVE_HTS
  837. return impl->setInterpolationWeight(index, weight);
  838. #else
  839. return false;
  840. #endif
  841. }
  842. /*!
  843. synthesize
  844. */
  845. bool Sinsy::synthesize(SynthCondition& condition)
  846. {
  847. #ifdef HAVE_HTS
  848. try {
  849. if (!impl->synthesize(*condition.impl)) {
  850. return false;
  851. }
  852. } catch (const std::exception& ex) {
  853. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  854. return false;
  855. }
  856. return true;
  857. #else
  858. return false;
  859. #endif
  860. }
  861. /*!
  862. stop
  863. */
  864. bool Sinsy::stop()
  865. {
  866. #ifdef HAVE_HTS
  867. try {
  868. impl->stop();
  869. } catch (const std::exception& ex) {
  870. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  871. return false;
  872. }
  873. return true;
  874. #else
  875. return false;
  876. #endif
  877. }
  878. /*!
  879. reset stop flag
  880. */
  881. bool Sinsy::resetStopFlag()
  882. {
  883. #ifdef HAVE_HTS
  884. try {
  885. impl->resetStopFlag();
  886. } catch (const std::exception& ex) {
  887. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  888. return false;
  889. }
  890. return true;
  891. #else
  892. return false;
  893. #endif
  894. }
  895. /*!
  896. clear score
  897. */
  898. bool Sinsy::clearScore()
  899. {
  900. try {
  901. impl->clearScore();
  902. } catch (const std::exception& ex) {
  903. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  904. return false;
  905. }
  906. return true;
  907. }
  908. /*!
  909. load score from MusicXML
  910. */
  911. bool Sinsy::loadScoreFromMusicXML(const std::string& xml)
  912. {
  913. try {
  914. InputFile xmlFile(xml);
  915. if(!xmlFile.isValid()) {
  916. ERR_MSG("Cannot open Xml file");
  917. return false;
  918. }
  919. if (!impl->loadScoreFromMusicXML(xmlFile)) {
  920. return false;
  921. }
  922. } catch (const std::exception& ex) {
  923. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  924. return false;
  925. }
  926. return true;
  927. }
  928. /*!
  929. save score to MusicXML
  930. */
  931. bool Sinsy::saveScoreToMusicXML(const std::string& xml, ClefType clefType)
  932. {
  933. try {
  934. XmlWriter::Clef clef(XmlWriter::CLEF_DEFAULT);
  935. switch (clefType) {
  936. case CLEFTYPE_DEFAULT :
  937. clef = XmlWriter::CLEF_DEFAULT;
  938. break;
  939. case CLEFTYPE_G :
  940. clef = XmlWriter::CLEF_G;
  941. break;
  942. case CLEFTYPE_F :
  943. clef = XmlWriter::CLEF_F;
  944. break;
  945. case CLEFTYPE_C :
  946. clef = XmlWriter::CLEF_C;
  947. break;
  948. default :
  949. ERR_MSG("Error in API " << FUNC_NAME("") << " : unknown clef type : " << clefType);
  950. break;
  951. }
  952. if (!impl->saveScoreToMusicXML(xml, clef)) {
  953. return false;
  954. }
  955. } catch (const std::exception& ex) {
  956. ERR_MSG("Exception in API " << FUNC_NAME("") << " : " << ex.what());
  957. return false;
  958. }
  959. return true;
  960. }
  961. }; // namespace sinsy