espeak-sg.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include <espeak-ng/espeak_ng.h>
  2. #define PLAYBACK_MODE (ENOUTPUT_MODE_SYNCHRONOUS | ENOUTPUT_MODE_SPEAK_AUDIO)
  3. #include <vector>
  4. #include <string>
  5. struct segment
  6. {
  7. char type;
  8. int start;
  9. int length;
  10. };
  11. struct pho_event
  12. {
  13. std::string code;
  14. int type;
  15. int start;
  16. };
  17. std::vector<short int> samples;
  18. std::vector<segment> segments;
  19. std::vector<pho_event> pho;
  20. char segment_type = 0;
  21. int segment_pos = 0;
  22. void init()
  23. {
  24. espeak_ng_InitializePath(NULL);
  25. espeak_ng_ERROR_CONTEXT context = NULL;
  26. espeak_ng_Initialize(&context);
  27. espeak_ng_InitializeOutput(ENOUTPUT_MODE_SYNCHRONOUS, 0, NULL); //FIX https://notabug.org/isengaara/sekai/issues/4
  28. }
  29. void segment_event(char type)
  30. {
  31. if(segment_type!=type)
  32. {
  33. if(segment_type!=0)
  34. {
  35. segment s;
  36. s.type = segment_type;
  37. s.start = segment_pos;
  38. s.length = samples.size()-segment_pos;
  39. segments.push_back(s);
  40. }
  41. segment_type = type;
  42. segment_pos = samples.size();
  43. }
  44. }
  45. void outputPhoSymbol(char* pho_code,int pho_type)
  46. {
  47. pho_event p;
  48. p.code = pho_code;
  49. p.type = pho_type;
  50. p.start = samples.size();
  51. pho.push_back(p);
  52. }
  53. void outputSilence(short int sample)
  54. {
  55. segment_event('S');
  56. samples.push_back(sample);
  57. }
  58. void outputUnvoiced(short int sample)
  59. {
  60. segment_event('U');
  61. samples.push_back(sample);
  62. }
  63. void outputVoiced(short int sample)
  64. {
  65. segment_event('V');
  66. samples.push_back(sample);
  67. }
  68. void flush()
  69. {
  70. outputPhoSymbol((char*)"#",0);
  71. segment_event(0);
  72. }
  73. void write_zstring(FILE* f,std::string s)
  74. {
  75. fwrite(s.c_str(),1,s.length()+1,f);
  76. }
  77. void write_int(FILE* f,int n)
  78. {
  79. fwrite(&n,1,sizeof(int),f);
  80. }
  81. void write_short(FILE* f,short n)
  82. {
  83. fwrite(&n,1,sizeof(short),f);
  84. }
  85. void write_char(FILE* f,char n)
  86. {
  87. fwrite(&n,1,sizeof(char),f);
  88. }
  89. void write_float(FILE* f,float n)
  90. {
  91. fwrite(&n,1,sizeof(float),f);
  92. }
  93. int main(int argc,char** argv)
  94. {
  95. if(argc<6)
  96. {
  97. printf("usage: espeak-sg voice f0 lyric rate filename\n");
  98. return 0;
  99. }
  100. char* voice = argv[1];
  101. int f0 = atoi(argv[2]);
  102. char* lyric = argv[3];
  103. int rate = atoi(argv[4]);
  104. char* filename = argv[5];
  105. init();
  106. espeak_ng_SetVoiceByName(voice);
  107. espeak_ng_OUTPUT_HOOKS hooks;
  108. hooks.outputPhoSymbol = outputPhoSymbol;
  109. hooks.outputSilence = outputSilence;
  110. hooks.outputUnvoiced = outputUnvoiced;
  111. hooks.outputVoiced = outputVoiced;
  112. espeak_ng_SetOutputHooks(&hooks);
  113. espeak_SetParameter(espeakRATE, rate, 0);
  114. float samplerate = (float)espeak_ng_GetSampleRate();
  115. espeak_ng_SetConstF0(f0);
  116. espeak_ng_Synthesize(lyric, 0, 0, POS_CHARACTER, 0, 0, NULL, NULL);
  117. flush();
  118. FILE* f = fopen(filename,"w");
  119. write_zstring(f,"espeak-sg");
  120. write_int(f,0); //version of the file format
  121. write_int(f,samplerate);
  122. write_int(f,f0);
  123. write_int(f,pho.size());
  124. for (auto i : pho)
  125. {
  126. write_zstring(f,i.code);
  127. write_int(f,i.type);
  128. write_int(f,i.start);
  129. }
  130. write_int(f,segments.size());
  131. for (auto i : segments)
  132. {
  133. write_char(f, i.type);
  134. write_int(f, i.start);
  135. write_int(f, i.length);
  136. }
  137. write_int(f,samples.size());
  138. fwrite(samples.data(),samples.size(),sizeof(short),f);
  139. fclose(f);
  140. return 0;
  141. }