plc_tests.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * plc_tests.c
  5. *
  6. * Written by Steve Underwood <steveu@coppice.org>
  7. *
  8. * Copyright (C) 2004 Steve Underwood
  9. *
  10. * All rights reserved.
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License version 2, as
  14. * published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24. */
  25. /*! \page plc_tests_page Packet loss concealment tests
  26. \section plc_tests_page_sec_1 What does it do?
  27. These tests run a speech file through the packet loss concealment routines.
  28. The loss rate, in percent, and the packet size, in samples, may be specified
  29. on the command line.
  30. \section plc_tests_page_sec_2 How are the tests run?
  31. These tests process a speech file called pre_plc.wav. This file should contain
  32. 8000 sample/second 16 bits/sample linear audio. The tests read this file in
  33. blocks, of a size specified on the command line. Some of these blocks are
  34. dropped, to simulate packet loss. The rate of loss is also specified on the
  35. command line. The PLC module is then used to reconstruct an acceptable
  36. approximation to the original signal. The resulting audio is written to a new
  37. audio file, called post_plc.wav. This file contains 8000 sample/second
  38. 16 bits/sample linear audio.
  39. */
  40. #if defined(HAVE_CONFIG_H)
  41. #include "config.h"
  42. #endif
  43. #include <stdlib.h>
  44. #include <stdio.h>
  45. #include <unistd.h>
  46. #include <string.h>
  47. #include <sndfile.h>
  48. #include "spandsp.h"
  49. #include "spandsp-sim.h"
  50. #define INPUT_FILE_NAME "../test-data/local/short_nb_voice.wav"
  51. #define OUTPUT_FILE_NAME "post_plc.wav"
  52. int main(int argc, char *argv[])
  53. {
  54. SNDFILE *inhandle;
  55. SNDFILE *outhandle;
  56. plc_state_t plc;
  57. int inframes;
  58. int outframes;
  59. int16_t amp[1024];
  60. int block_no;
  61. int lost_blocks;
  62. int block_len;
  63. int loss_rate;
  64. int dropit;
  65. int tone;
  66. int i;
  67. int opt;
  68. bool block_real;
  69. bool block_synthetic;
  70. uint32_t phase_acc;
  71. int32_t phase_rate;
  72. loss_rate = 25;
  73. block_len = 160;
  74. block_real = false;
  75. block_synthetic = false;
  76. tone = -1;
  77. while ((opt = getopt(argc, argv, "b:l:rst:")) != -1)
  78. {
  79. switch (opt)
  80. {
  81. case 'b':
  82. block_len = atoi(optarg);
  83. break;
  84. case 'l':
  85. loss_rate = atoi(optarg);
  86. break;
  87. case 'r':
  88. block_real = true;
  89. break;
  90. case 's':
  91. block_synthetic = true;
  92. break;
  93. case 't':
  94. tone = atoi(optarg);
  95. break;
  96. }
  97. }
  98. phase_rate = 0;
  99. inhandle = NULL;
  100. if (tone < 0)
  101. {
  102. if ((inhandle = sf_open_telephony_read(INPUT_FILE_NAME, 1)) == NULL)
  103. {
  104. fprintf(stderr, " Failed to open audio file '%s'\n", INPUT_FILE_NAME);
  105. exit(2);
  106. }
  107. }
  108. else
  109. {
  110. phase_rate = dds_phase_ratef((float) tone);
  111. }
  112. if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 1)) == NULL)
  113. {
  114. fprintf(stderr, " Failed to open audio file '%s'\n", OUTPUT_FILE_NAME);
  115. exit(2);
  116. }
  117. plc_init(&plc);
  118. lost_blocks = 0;
  119. for (block_no = 0; ; block_no++)
  120. {
  121. if (tone < 0)
  122. {
  123. inframes = sf_readf_short(inhandle, amp, block_len);
  124. if (inframes != block_len)
  125. break;
  126. }
  127. else
  128. {
  129. if (block_no > 10000)
  130. break;
  131. for (i = 0; i < block_len; i++)
  132. amp[i] = (int16_t) dds_modf(&phase_acc, phase_rate, 10000.0, 0);
  133. inframes = block_len;
  134. }
  135. dropit = rand()/(RAND_MAX/100);
  136. if (dropit > loss_rate)
  137. {
  138. plc_rx(&plc, amp, inframes);
  139. if (block_real)
  140. memset(amp, 0, sizeof(int16_t)*inframes);
  141. }
  142. else
  143. {
  144. lost_blocks++;
  145. plc_fillin(&plc, amp, inframes);
  146. if (block_synthetic)
  147. memset(amp, 0, sizeof(int16_t)*inframes);
  148. }
  149. outframes = sf_writef_short(outhandle, amp, inframes);
  150. if (outframes != inframes)
  151. {
  152. fprintf(stderr, " Error writing out sound\n");
  153. exit(2);
  154. }
  155. }
  156. printf("Dropped %d of %d blocks\n", lost_blocks, block_no);
  157. if (tone < 0)
  158. {
  159. if (sf_close_telephony(inhandle))
  160. {
  161. fprintf(stderr, " Cannot close audio file '%s'\n", INPUT_FILE_NAME);
  162. exit(2);
  163. }
  164. }
  165. if (sf_close_telephony(outhandle))
  166. {
  167. fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
  168. exit(2);
  169. }
  170. return 0;
  171. }
  172. /*- End of function --------------------------------------------------------*/
  173. /*- End of file ------------------------------------------------------------*/