find_sts_main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*************************************************************************/
  2. /* */
  3. /* Language Technologies Institute */
  4. /* Carnegie Mellon University */
  5. /* Copyright (c) 2001 */
  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: June 2001 */
  35. /*************************************************************************/
  36. /* */
  37. /* residuals etc */
  38. /* */
  39. /*************************************************************************/
  40. #include <stdio.h>
  41. #include <math.h>
  42. #include <string.h>
  43. /* To allow some normally const fields to manipulated during building */
  44. #define const
  45. #include "cst_args.h"
  46. #include "cst_wave.h"
  47. #include "cst_track.h"
  48. #include "cst_sigpr.h"
  49. float lpc_min;
  50. float lpc_range;
  51. char *residual_codec = "ulaw";
  52. cst_track *vuv;
  53. void inv_lpc_filterd(short *sig, float *a, int order, double *res, int size)
  54. {
  55. /* Note this address bytes before sig, up to order shorts back */
  56. int i, j;
  57. double r;
  58. for (i = 0; i < size; i++)
  59. {
  60. r = sig[i];
  61. for (j = 1; j < order; j++)
  62. r -= a[j] * (double)sig[i - j];
  63. res[i] = r;
  64. }
  65. }
  66. static int voiced_frame(cst_track *lpc,int i,cst_track *vuv)
  67. {
  68. int p;
  69. p = lpc->times[i]/(vuv->times[1]-vuv->times[0]);
  70. if (p < 2) /* some reasonable edge conditions */
  71. return 0; /* unvoiced */
  72. else if (p+2 >= vuv->num_frames)
  73. return 0; /* unvoiced */
  74. else if (vuv->frames[p][0] == 1)
  75. return 1; /* voiced */
  76. else if ((vuv->frames[p-2][0] == 0) &&
  77. (vuv->frames[p-1][0] == 0) &&
  78. (vuv->frames[p+1][0] == 0) &&
  79. (vuv->frames[p+2][0] == 0)
  80. )
  81. return 0; /* unvoiced */
  82. else
  83. return 1;
  84. }
  85. cst_sts *find_sts(cst_wave *sig, cst_track *lpc)
  86. {
  87. cst_sts *sts;
  88. int i,j;
  89. double *resd;
  90. int size,start,end;
  91. short *sigplus;
  92. unsigned char *ulaw_res, *power;
  93. int ipower;
  94. float sump;
  95. int packed_size;
  96. #if 0
  97. unsigned char *residual_unpacked;
  98. int frame_size;
  99. #endif
  100. sts = cst_alloc(cst_sts,lpc->num_frames);
  101. sigplus = cst_alloc(short,sig->num_samples+lpc->num_channels);
  102. memset(sigplus,0,sizeof(short)*lpc->num_channels);
  103. memmove(&sigplus[lpc->num_channels],
  104. sig->samples,
  105. sizeof(short)*sig->num_samples);
  106. /* EST LPC Windows are centered around the point */
  107. /* so offset things by a half period */
  108. start = (int)((float)sig->sample_rate * lpc->times[0]/2);
  109. for (i=0; i<lpc->num_frames; i++)
  110. {
  111. if (i+1 == lpc->num_frames)
  112. end = (int)((float)sig->sample_rate * lpc->times[i]);
  113. else
  114. end = (int)((float)sig->sample_rate *
  115. (lpc->times[i]+lpc->times[i+1]))/2;
  116. size = end - start;
  117. if (size == 0)
  118. printf("frame size at %f is 0\n",lpc->times[i]);
  119. resd = cst_alloc(double,size);
  120. inv_lpc_filterd(&sigplus[start+lpc->num_channels],
  121. lpc->frames[i],lpc->num_channels,
  122. resd,
  123. size);
  124. sts[i].size = size;
  125. sts[i].frame = cst_alloc(unsigned short,lpc->num_channels-1);
  126. for (j=1; j < lpc->num_channels; j++)
  127. sts[i].frame[j-1] = (unsigned short)
  128. (((lpc->frames[i][j]-lpc_min)/lpc_range)*65535);
  129. if (cst_streq(residual_codec,"ulaw"))
  130. {
  131. sts[i].residual = cst_alloc(unsigned char,size);
  132. for (j=0; j < size; j++)
  133. sts[i].residual[j] = cst_short_to_ulaw((short)resd[j]);
  134. }
  135. else if (cst_streq(residual_codec,"g721"))
  136. {
  137. ulaw_res = cst_alloc(unsigned char,size+CST_G721_LEADIN);
  138. for (j=0; j < size+CST_G721_LEADIN; j++)
  139. ulaw_res[j] = cst_short_to_ulaw((short)resd[j-CST_G721_LEADIN]);
  140. sts[i].residual = cst_g721_encode(&packed_size,size+CST_G721_LEADIN,ulaw_res);
  141. cst_free(ulaw_res);
  142. }
  143. else if (cst_streq(residual_codec,"g721vuv"))
  144. {
  145. sump = 0.0;
  146. for (j=0; j < size; j++)
  147. sump+=resd[j]*resd[j];
  148. ipower = (int)sqrt(sump/size);
  149. if (voiced_frame(lpc,i,vuv) || (ipower > 250))
  150. {
  151. ulaw_res = cst_alloc(unsigned char,size+CST_G721_LEADIN);
  152. for (j=0; j < size+CST_G721_LEADIN; j++)
  153. ulaw_res[j] = cst_short_to_ulaw((short)resd[j-CST_G721_LEADIN]);
  154. sts[i].residual = cst_g721_encode(&packed_size,size+CST_G721_LEADIN,ulaw_res);
  155. cst_free(ulaw_res);
  156. }
  157. else /* Unvoiced frame */
  158. {
  159. power = cst_alloc(unsigned char,6);
  160. power[0] = 0;
  161. power[1] = (unsigned char)ipower%256;
  162. ipower = ipower >> 8;
  163. power[2] = (unsigned char)ipower%256;
  164. ipower = ipower >> 8;
  165. power[3] = (unsigned char)ipower%256;
  166. ipower = ipower >> 8;
  167. power[4] = (unsigned char)ipower%256;
  168. sts[i].residual = power;
  169. }
  170. }
  171. else if (cst_streq(residual_codec,"vuv"))
  172. {
  173. sump = 0.0;
  174. for (j=0; j < size; j++)
  175. sump+=resd[j]*resd[j];
  176. ipower = (int)sqrt(sump/size);
  177. if (voiced_frame(lpc,i,vuv) || ipower > 250)
  178. {
  179. sts[i].residual = cst_alloc(unsigned char,size);
  180. for (j=0; j < size; j++)
  181. sts[i].residual[j] = cst_short_to_ulaw((short)resd[j]);
  182. }
  183. else /* Unvoiced frame */
  184. {
  185. sump = 0.0;
  186. for (j=0; j < size; j++)
  187. sump+=resd[j]*resd[j];
  188. power = cst_alloc(unsigned char,6);
  189. power[0] = 0;
  190. power[1] = (unsigned char)ipower%256;
  191. ipower = ipower >> 8;
  192. power[2] = (unsigned char)ipower%256;
  193. ipower = ipower >> 8;
  194. power[3] = (unsigned char)ipower%256;
  195. ipower = ipower >> 8;
  196. power[4] = (unsigned char)ipower%256;
  197. sts[i].residual = power;
  198. }
  199. }
  200. else
  201. {
  202. fprintf(stderr,"unknown codec \'%s\"\n",residual_codec);
  203. exit(-1);
  204. }
  205. start = end;
  206. }
  207. cst_free(sigplus);
  208. return sts;
  209. }
  210. static double plus_or_minus_one()
  211. {
  212. /* Randomly return 1 or -1 */
  213. /* not sure rand() is portable */
  214. if (rand() > RAND_MAX/2.0)
  215. return 1.0;
  216. else
  217. return -1.0;
  218. }
  219. static double rand_zero_to_one()
  220. {
  221. /* Return number between 0.0 and 1.0 */
  222. return rand()/(float)RAND_MAX;
  223. }
  224. cst_wave *reconstruct_wave(cst_wave *sig, cst_sts *sts, cst_track *lpc)
  225. {
  226. cst_lpcres *lpcres;
  227. int i,j,r;
  228. int start;
  229. int num_samples;
  230. unsigned char *residual_unpacked;
  231. int frame_size;
  232. int p;
  233. float m, q;
  234. FILE *ofd; int s;
  235. for (num_samples = 0, i=0; i < lpc->num_frames; i++)
  236. num_samples += sts[i].size;
  237. lpcres = new_lpcres();
  238. lpcres_resize_frames(lpcres,lpc->num_frames);
  239. lpcres->num_channels = lpc->num_channels-1;
  240. start = (int)((float)sig->sample_rate * lpc->times[0]/2);
  241. num_samples += start;
  242. for (i=0; i<lpc->num_frames; i++)
  243. {
  244. lpcres->frames[i] = sts[i].frame;
  245. lpcres->sizes[i] = sts[i].size;
  246. }
  247. lpcres_resize_samples(lpcres,num_samples);
  248. lpcres->lpc_min = lpc_min;
  249. lpcres->lpc_range = lpc_range;
  250. lpcres->sample_rate = sig->sample_rate;
  251. for (r=start,i=0; i<lpc->num_frames; i++)
  252. {
  253. if (cst_streq(residual_codec,"g721"))
  254. {
  255. residual_unpacked =
  256. cst_g721_decode(&frame_size, (sts[i].size+CST_G721_LEADIN+1)/2, sts[i].residual);
  257. for (j=0; j<sts[i].size; j++,r++)
  258. lpcres->residual[r] = residual_unpacked[j+CST_G721_LEADIN];
  259. cst_free(residual_unpacked);
  260. }
  261. else if (cst_streq(residual_codec,"g721vuv"))
  262. {
  263. if (sts[i].residual[0] == 0)
  264. {
  265. p = sts[i].residual[4]; p = p << 8;
  266. p += sts[i].residual[3]; p = p << 8;
  267. p += sts[i].residual[2]; p = p << 8;
  268. p += sts[i].residual[1];
  269. m = ((float)p);
  270. for (j=0; j<sts[i].size; j++,r++)
  271. {
  272. q = m*2*rand_zero_to_one()*plus_or_minus_one();
  273. lpcres->residual[r] = cst_short_to_ulaw((short)q);
  274. }
  275. }
  276. else
  277. {
  278. residual_unpacked =
  279. cst_g721_decode(&frame_size, (sts[i].size+CST_G721_LEADIN+1)/2, sts[i].residual);
  280. for (j=0; j<sts[i].size; j++,r++)
  281. lpcres->residual[r] = residual_unpacked[j+CST_G721_LEADIN];
  282. cst_free(residual_unpacked);
  283. }
  284. }
  285. else if (cst_streq(residual_codec,"vuv"))
  286. {
  287. if (sts[i].residual[0] == 0)
  288. {
  289. p = sts[i].residual[4]; p = p << 8;
  290. p += sts[i].residual[3]; p = p << 8;
  291. p += sts[i].residual[2]; p = p << 8;
  292. p += sts[i].residual[1];
  293. m = ((float)p);
  294. for (j=0; j<sts[i].size; j++,r++)
  295. {
  296. q = m*2*rand_zero_to_one()*plus_or_minus_one();
  297. lpcres->residual[r] = cst_short_to_ulaw((short)q);
  298. }
  299. }
  300. else
  301. {
  302. for (j=0; j<sts[i].size; j++,r++)
  303. lpcres->residual[r] = sts[i].residual[j];
  304. }
  305. }
  306. else /* ulaw */
  307. {
  308. for (j=0; j<sts[i].size; j++,r++)
  309. lpcres->residual[r] = sts[i].residual[j];
  310. }
  311. }
  312. #if 1
  313. /* Debug dump */
  314. ofd = fopen("lpc_resid.lpc","w");
  315. for (s=0,i=0; i<lpcres->num_frames; i++)
  316. {
  317. fprintf(ofd,"%d %d %d\n",i,0,lpcres->sizes[i]);
  318. for (j=0; j < lpcres->num_channels; j++)
  319. fprintf(ofd,"%d ",lpcres->frames[i][j]);
  320. fprintf(ofd,"\n");
  321. fprintf(ofd,"%d ",32000); s++;
  322. for (j=1; j < lpcres->sizes[i]; j++,s++)
  323. fprintf(ofd,"%d ",cst_ulaw_to_short(lpcres->residual[s]));
  324. fprintf(ofd,"\n");
  325. }
  326. fclose(ofd);
  327. ofd = fopen("lpc_resid.res","w");
  328. for (i=0; i < r; i++)
  329. fprintf(ofd,"%d\n",cst_ulaw_to_short(lpcres->residual[i]));
  330. fclose(ofd);
  331. #endif
  332. return lpc_resynth_fixedpoint(lpcres);
  333. }
  334. void compare_waves(cst_wave *a, cst_wave *b)
  335. {
  336. int i;
  337. double r;
  338. if (a->num_samples != b->num_samples)
  339. {
  340. if (a->num_samples > b->num_samples)
  341. {
  342. compare_waves(b,a);
  343. return;
  344. }
  345. }
  346. for (r=0.0,i=0; i<a->num_samples; i++)
  347. r += ((float)a->samples[i]-(float)b->samples[i]) *
  348. ((float)a->samples[i]-(float)b->samples[i]);
  349. r /= a->num_samples;
  350. printf("a/b diff %f\n",sqrt(r));
  351. }
  352. void save_sts(cst_sts *sts, cst_track *lpc, cst_wave *sig, const char *fn)
  353. {
  354. FILE *fd;
  355. int i,j;
  356. if ((fd=fopen(fn,"w"))== NULL)
  357. {
  358. fprintf(stderr,"can't open for writing file: %s\n", fn);
  359. exit(-1);
  360. }
  361. fprintf(fd,"( %d %d %d %f %f)\n", lpc->num_frames,
  362. lpc->num_channels-1, sig->sample_rate,
  363. lpc_min, lpc_range);
  364. for (i=0; i<lpc->num_frames; i++)
  365. {
  366. fprintf(fd,"( %f (",lpc->times[i]);
  367. for (j=1; j < lpc->num_channels; j++)
  368. fprintf(fd," %d",sts[i].frame[j-1]);
  369. fprintf(fd," ) %d ( ", sts[i].size);
  370. if (cst_streq(residual_codec,"ulaw"))
  371. {
  372. for (j=0; j < sts[i].size; j++)
  373. fprintf(fd," %d",sts[i].residual[j]);
  374. }
  375. else if (cst_streq(residual_codec,"g721"))
  376. {
  377. for (j=0; j < (sts[i].size+CST_G721_LEADIN+1)/2; j++)
  378. fprintf(fd," %d",sts[i].residual[j]);
  379. }
  380. else if (cst_streq(residual_codec,"g721vuv"))
  381. {
  382. if (sts[i].residual[0] == 0)
  383. for (j=0; j < 5; j++)
  384. fprintf(fd," %d",sts[i].residual[j]);
  385. else
  386. for (j=0; j < (sts[i].size+CST_G721_LEADIN+1)/2; j++)
  387. fprintf(fd," %d",sts[i].residual[j]);
  388. }
  389. else if (cst_streq(residual_codec,"vuv"))
  390. {
  391. if (sts[i].residual[0] == 0)
  392. for (j=0; j < 5; j++)
  393. fprintf(fd," %d",sts[i].residual[j]);
  394. else
  395. for (j=0; j < sts[i].size; j++)
  396. fprintf(fd," %d",sts[i].residual[j]);
  397. }
  398. fprintf(fd," ))\n");
  399. }
  400. fclose(fd);
  401. }
  402. int main(int argc, char **argv)
  403. {
  404. cst_track *lpc;
  405. cst_wave *sig, *sig2;
  406. cst_sts *sts;
  407. cst_features *args;
  408. args = new_features();
  409. cst_args(argv,argc,
  410. "usage: find_sts OPTIONS\n"
  411. "Find sts from lpc and waveform\n"
  412. "-codec <string> ulaw (default), g721, g721vuv, vuv\n"
  413. "-vuv <string> v/uv track (for some codecs)\n"
  414. "-lpcmin <float> minimum LPC value\n"
  415. "-lpcrange <float> range of LPC values\n"
  416. "-lpc <string> LPC track file\n"
  417. "-wave <string> WAVE file\n"
  418. "-o <string> STS output file\n",
  419. args);
  420. lpc_min = get_param_float(args,"-lpcmin",-10.0);
  421. lpc_range = get_param_float(args,"-lpcrange",20.0);
  422. residual_codec = get_param_string(args,"-codec","ulaw");
  423. if (feat_present(args,"-vuv"))
  424. {
  425. /* Fixed frame track of voiced (1) unvoived (0) information */
  426. vuv = new_track();
  427. cst_track_load_est(vuv,get_param_string(args,"-vuv","file.vuv"));
  428. }
  429. lpc = new_track();
  430. cst_track_load_est(lpc,get_param_string(args,"-lpc","file.lpc"));
  431. sig = new_wave();
  432. if (cst_wave_load_riff(sig,get_param_string(args,"-wave","file.wav"))
  433. == CST_WRONG_FORMAT)
  434. {
  435. fprintf(stderr,
  436. "cannot load waveform, format unrecognized, from \"%s\"\n",
  437. get_param_string(args,"-wave","file.wav"));
  438. exit(-1);
  439. }
  440. sts = find_sts(sig,lpc);
  441. /* See if it worked */
  442. sig2 = reconstruct_wave(sig,sts,lpc);
  443. compare_waves(sig,sig2);
  444. cst_wave_save_riff(sig2,"sig2.wav");
  445. save_sts(sts,lpc,sig,get_param_string(args,"-o","file.sts"));
  446. return 0;
  447. }