lpc_resynth_main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*************************************************************************/
  2. /* */
  3. /* Language Technologies Institute */
  4. /* Carnegie Mellon University */
  5. /* Copyright (c) 2010 */
  6. /* All Rights Reserved. */
  7. /* */
  8. /* Permission is hereby granted, free of charge, to use and distribute */
  9. /* this software and its documentation without restriction, including */
  10. /* without limitation the rights to use, copy, modify, merge, publish, */
  11. /* distribute, sublicense, and/or sell copies of this work, and to */
  12. /* permit persons to whom this work is furnished to do so, subject to */
  13. /* the following conditions: */
  14. /* 1. The code must retain the above copyright notice, this list of */
  15. /* conditions and the following disclaimer. */
  16. /* 2. Any modifications must be clearly marked as such. */
  17. /* 3. Original authors' names are not deleted. */
  18. /* 4. The authors' names are not used to endorse or promote products */
  19. /* derived from this software without specific prior written */
  20. /* permission. */
  21. /* */
  22. /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */
  23. /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
  24. /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
  25. /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */
  26. /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
  27. /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
  28. /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
  29. /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
  30. /* THIS SOFTWARE. */
  31. /* */
  32. /*************************************************************************/
  33. /* Author: Alan W Black (awb@cs.cmu.edu) */
  34. /* Date: April 2010 */
  35. /*************************************************************************/
  36. /* */
  37. /* Resynthesize lpc with various techniques */
  38. /*************************************************************************/
  39. #include <stdio.h>
  40. #include "flite.h"
  41. #include "cst_track.h"
  42. #include "cst_wave.h"
  43. #include "cst_tokenstream.h"
  44. #include "cst_args.h"
  45. #include "cst_math.h"
  46. void lpc2ref(const float *lpc, float *rfc, int order);
  47. void ref2lpc(const float *rfc, float *lpc, int order);
  48. static double plus_or_minus_one()
  49. {
  50. /* Randomly return 1 or -1 */
  51. /* not sure rand() is portable */
  52. if (rand() > RAND_MAX/2.0)
  53. return 1.0;
  54. else
  55. return -1.0;
  56. }
  57. static double rand_zero_to_one()
  58. {
  59. /* Return number between 0.0 and 1.0 */
  60. return rand()/(float)RAND_MAX;
  61. }
  62. int main(int argc, char **argv)
  63. {
  64. cst_track *t1;
  65. cst_track *me_filters=NULL;
  66. cst_wave *w1, *w2, *res=NULL;
  67. cst_val *files;
  68. cst_features *args;
  69. int i, j;
  70. int order, o, s;
  71. int frame_length;
  72. float *lpcs, *residual;
  73. float m;
  74. const char *f1, *f2;
  75. const char *resfn = NULL;
  76. int last_peak = 0, next_peak;
  77. int period;
  78. float power;
  79. int rfc=0;
  80. int str=0;
  81. int fn, fo, ss;
  82. float xpulse, xnoise;
  83. float fxpulse, fxnoise;
  84. float x, me;
  85. float *hpulse=NULL, *hnoise=NULL;
  86. float *xpulsesig=NULL, *xnoisesig=NULL;
  87. int q=0;
  88. int position;
  89. int lpc_start = 0;
  90. args = new_features();
  91. files =
  92. cst_args(argv,argc,
  93. "usage: lpc_resynth OPTIONS INTRACK OUTWAVE\n"
  94. "Resynth an lpc track\n"
  95. "-res <string> residual (as waveform)\n"
  96. "-save_res Save the generated residual\n"
  97. "-lpc_start <int> start of lpc params in lpc track {1}\n"
  98. "-order <int> LPC order {16}\n"
  99. "-str mixed excitation strengths\n"
  100. "-me_filters <string> mixed excitation filters\n"
  101. "-rfc Coefficents are reflection coefficients\n",
  102. args);
  103. f1 = val_string(val_car(files));
  104. f2 = val_string(val_car(val_cdr(files)));
  105. t1 = new_track();
  106. lpc_start = flite_get_param_int(args,"-lpc_start",1);
  107. if (feat_present(args,"-rfc"))
  108. rfc = 1;
  109. if (feat_present(args,"-str"))
  110. str = 1;
  111. if (feat_present(args,"-me_filters"))
  112. {
  113. me_filters = new_track();
  114. if (cst_track_load_est(me_filters,flite_get_param_string(args,"-me_filters","me_filters.track")) != CST_OK_FORMAT)
  115. {
  116. fprintf(stderr,
  117. "lpc_resynth: can't read file or wrong format \"%s\"\n",
  118. f1);
  119. return -1;
  120. }
  121. hpulse = cst_alloc(float,me_filters->num_channels);
  122. hnoise = cst_alloc(float,me_filters->num_channels);
  123. xpulsesig = cst_alloc(float,me_filters->num_channels);
  124. xnoisesig = cst_alloc(float,me_filters->num_channels);
  125. }
  126. if (cst_track_load_est(t1,f1) != CST_OK_FORMAT)
  127. {
  128. fprintf(stderr,
  129. "lpc_resynth: can't read file or wrong format \"%s\"\n",
  130. f1);
  131. return -1;
  132. }
  133. w1 = new_wave();
  134. w1->sample_rate = 16000;
  135. cst_wave_resize(w1,160+(int)(t1->times[t1->num_frames-1]*w1->sample_rate),1);
  136. if (feat_present(args,"-res"))
  137. {
  138. res = new_wave();
  139. resfn = flite_get_param_string(args,"-res","res.wav");
  140. if (cst_wave_load_riff(res,resfn) != CST_OK_FORMAT)
  141. {
  142. fprintf(stderr,
  143. "lpc_resynth: can't read file or wrong format \"%s\"\n",
  144. resfn);
  145. }
  146. }
  147. w2 = copy_wave(w1);
  148. order = flite_get_param_int(args,"-order",16);
  149. lpcs = cst_alloc(float,order);
  150. s = order;
  151. residual = NULL;
  152. for (i=1; i<t1->num_frames; i++)
  153. {
  154. frame_length = 10+(int)(w1->sample_rate*t1->times[i])-s;
  155. cst_free(residual);
  156. residual = cst_alloc(float,frame_length);
  157. /* LPC coefficients */
  158. if (rfc == 1)
  159. ref2lpc(&(t1->frames[i][lpc_start]),lpcs,order);
  160. else
  161. {
  162. for (o=0; o<order; o++)
  163. lpcs[o] = t1->frames[i][lpc_start+o];
  164. }
  165. /* Residual */
  166. /* Mixed excitation residual */
  167. if (str)
  168. {
  169. for (fo=0; fo<me_filters->num_channels; fo++)
  170. {
  171. hpulse[fo] = hnoise[fo] = 0.0;
  172. ss=order+2;
  173. for (fn=0; fn<me_filters->num_frames; fn++)
  174. {
  175. me = me_filters->frames[fn][fo];
  176. hpulse[fo] += t1->frames[i][ss+fn] * me;
  177. hnoise[fo] += (1 - t1->frames[i][ss+fn]) * me;
  178. }
  179. }
  180. /* For each sample in the frame */
  181. for (j=0; j<frame_length; j++)
  182. {
  183. xnoise = plus_or_minus_one();
  184. if (t1->frames[i][0] == 0)
  185. {
  186. xpulse = 0.0; /* unvoiced */
  187. }
  188. else
  189. { /* voiced */
  190. period = w1->sample_rate/t1->frames[i][0];
  191. next_peak = last_peak + period;
  192. #if 0
  193. if (next_peak < (s + j))
  194. { /* voiced peak in this frame */
  195. xpulse = sqrt(period); /* sqrt ??? */
  196. last_peak = next_peak;
  197. }
  198. #endif
  199. #if 1
  200. if (q == 3)
  201. {
  202. xpulse = sqrt(period)/4.0; q--;
  203. }
  204. else if (q == 2)
  205. {
  206. xpulse = sqrt(period)/2.0; q--;
  207. }
  208. else if (q == 1)
  209. {
  210. xpulse = sqrt(period)/4.0; q--;
  211. }
  212. else if (next_peak < (s + j))
  213. {
  214. xpulse = sqrt(period)/4.0;
  215. q = 3;
  216. last_peak = next_peak;
  217. }
  218. #endif
  219. else
  220. xpulse = 0;
  221. }
  222. fxpulse = fxnoise = 0.0;
  223. for (fo=me_filters->num_channels-1; fo>0; fo--)
  224. {
  225. fxpulse += hpulse[fo] * xpulsesig[fo];
  226. fxnoise += hnoise[fo] * xnoisesig[fo];
  227. xpulsesig[fo] = xpulsesig[fo-1];
  228. xnoisesig[fo] = xnoisesig[fo-1];
  229. }
  230. fxpulse += hpulse[0] * xpulse;
  231. fxnoise += hnoise[0] * xnoise;
  232. xpulsesig[0] = xpulse;
  233. xnoisesig[0] = xnoise;
  234. x = fxpulse + fxnoise; /* excitation is pulse plus noise */
  235. residual[j] = x * sqrt(t1->frames[i][1]);
  236. }
  237. }
  238. /* predefined residual */
  239. else if (resfn)
  240. {
  241. for (j=0; j<frame_length; j++)
  242. residual[j] = res->samples[s-order+j];
  243. }
  244. /* Spike plus white noise */
  245. else if ((t1->frames[i][0] == 0) ||
  246. (t1->frames[i][t1->num_channels-1] == 0))
  247. { /* unvoiced */
  248. printf("awb_debug unvoiced %d\n",i);
  249. m = sqrt(t1->frames[i][1]);
  250. for (j=0; j<frame_length; j++)
  251. residual[j] = m*rand_zero_to_one()*plus_or_minus_one();
  252. last_peak = s; /* identify where next pulse should be */
  253. }
  254. else
  255. { /* voiced */
  256. printf("awb_debug voiced %d\n",i);
  257. period = w1->sample_rate/t1->frames[i][0];
  258. next_peak = last_peak + period;
  259. memset(residual,0,sizeof(float)*frame_length);
  260. if (next_peak < (s + frame_length))
  261. {
  262. printf("awb_debug ping voiced %d\n",i);
  263. power = sqrt(t1->frames[i][1])*frame_length;
  264. if (next_peak-s < 2)
  265. position=2;
  266. else
  267. position=next_peak-s;
  268. residual[position-2] = power/4;
  269. residual[position-1] = power/2;
  270. residual[position] = power/4;
  271. last_peak = next_peak;
  272. }
  273. }
  274. /* LPC resynthesis */
  275. for (j=0; j< frame_length; j++)
  276. {
  277. w1->samples[s] = residual[j];
  278. w2->samples[s] = residual[j];
  279. for (o=0; (o < order) && ((s-order) > 0); o++)
  280. w1->samples[s] += lpcs[o]*w1->samples[s-o-1];
  281. s++;
  282. }
  283. }
  284. cst_wave_save_riff(w1,f2);
  285. if (feat_present(args,"-save_res"))
  286. cst_wave_save_riff(w2,"residual.wav");
  287. cst_free(residual);
  288. cst_free(hpulse);
  289. cst_free(hnoise);
  290. cst_free(xpulsesig);
  291. cst_free(xnoisesig);
  292. delete_features(args);
  293. delete_wave(w1);
  294. delete_wave(w2);
  295. delete_wave(res);
  296. delete_track(t1);
  297. delete_track(me_filters);
  298. return 0;
  299. }