123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- #include <espeak-ng/espeak_ng.h>
- #define PLAYBACK_MODE (ENOUTPUT_MODE_SYNCHRONOUS | ENOUTPUT_MODE_SPEAK_AUDIO)
- #include <vector>
- #include <string>
- struct segment
- {
- char type;
- int start;
- int length;
- };
- struct pho_event
- {
- std::string code;
- int type;
- int start;
- };
- std::vector<short int> samples;
- std::vector<segment> segments;
- std::vector<pho_event> pho;
- char segment_type = 0;
- int segment_pos = 0;
- void init()
- {
- espeak_ng_InitializePath(NULL);
-
- espeak_ng_ERROR_CONTEXT context = NULL;
- espeak_ng_Initialize(&context);
-
- espeak_ng_InitializeOutput(ENOUTPUT_MODE_SYNCHRONOUS, 0, NULL); //FIX https://notabug.org/isengaara/sekai/issues/4
- }
- void segment_event(char type)
- {
- if(segment_type!=type)
- {
- if(segment_type!=0)
- {
- segment s;
- s.type = segment_type;
- s.start = segment_pos;
- s.length = samples.size()-segment_pos;
- segments.push_back(s);
- }
- segment_type = type;
- segment_pos = samples.size();
- }
- }
- void outputPhoSymbol(char* pho_code,int pho_type)
- {
- pho_event p;
- p.code = pho_code;
- p.type = pho_type;
- p.start = samples.size();
- pho.push_back(p);
-
- }
- void outputSilence(short int sample)
- {
- segment_event('S');
- samples.push_back(sample);
- }
- void outputUnvoiced(short int sample)
- {
- segment_event('U');
- samples.push_back(sample);
- }
- void outputVoiced(short int sample)
- {
- segment_event('V');
- samples.push_back(sample);
- }
- void flush()
- {
- outputPhoSymbol((char*)"#",0);
- segment_event(0);
- }
- void write_zstring(FILE* f,std::string s)
- {
- fwrite(s.c_str(),1,s.length()+1,f);
- }
- void write_int(FILE* f,int n)
- {
- fwrite(&n,1,sizeof(int),f);
- }
- void write_short(FILE* f,short n)
- {
- fwrite(&n,1,sizeof(short),f);
- }
- void write_char(FILE* f,char n)
- {
- fwrite(&n,1,sizeof(char),f);
- }
- void write_float(FILE* f,float n)
- {
- fwrite(&n,1,sizeof(float),f);
- }
- int main(int argc,char** argv)
- {
- if(argc<6)
- {
- printf("usage: espeak-sg voice f0 lyric rate filename\n");
- return 0;
- }
-
- char* voice = argv[1];
- int f0 = atoi(argv[2]);
- char* lyric = argv[3];
- int rate = atoi(argv[4]);
- char* filename = argv[5];
-
-
-
-
-
-
- init();
- espeak_ng_SetVoiceByName(voice);
-
- espeak_ng_OUTPUT_HOOKS hooks;
- hooks.outputPhoSymbol = outputPhoSymbol;
- hooks.outputSilence = outputSilence;
- hooks.outputUnvoiced = outputUnvoiced;
- hooks.outputVoiced = outputVoiced;
- espeak_ng_SetOutputHooks(&hooks);
-
- espeak_SetParameter(espeakRATE, rate, 0);
-
-
- float samplerate = (float)espeak_ng_GetSampleRate();
- espeak_ng_SetConstF0(f0);
- espeak_ng_Synthesize(lyric, 0, 0, POS_CHARACTER, 0, 0, NULL, NULL);
-
- flush();
-
- FILE* f = fopen(filename,"w");
- write_zstring(f,"espeak-sg");
- write_int(f,0); //version of the file format
- write_int(f,samplerate);
- write_int(f,f0);
-
-
- write_int(f,pho.size());
- for (auto i : pho)
- {
- write_zstring(f,i.code);
- write_int(f,i.type);
- write_int(f,i.start);
- }
-
- write_int(f,segments.size());
- for (auto i : segments)
- {
- write_char(f, i.type);
- write_int(f, i.start);
- write_int(f, i.length);
- }
-
- write_int(f,samples.size());
- fwrite(samples.data(),samples.size(),sizeof(short),f);
-
- fclose(f);
-
- return 0;
- }
|