2
0

ima_adpcm_tests.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * ima_adpcm_tests.c - Test the IMA/DVI/Intel ADPCM encode and decode
  5. * software.
  6. *
  7. * Written by Steve Underwood <steveu@coppice.org>
  8. *
  9. * Copyright (C) 2004 Steve Underwood
  10. *
  11. * All rights reserved.
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License version 2, as
  15. * published by the Free Software Foundation.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. */
  26. /*! \file */
  27. /*! \page ima_adpcm_tests_page IMA ADPCM tests
  28. \section ima_adpcm_tests_page_sec_1 What does it do?
  29. To perform a general audio quality test, ima_adpcm_tests should be run. The test file
  30. ../test-data/local/short_nb_voice.wav will be compressed to the specified bit rate,
  31. decompressed, and the resulting audio stored in post_ima_adpcm.wav. A simple SNR test
  32. is automatically performed. Listening tests may be used for a more detailed evaluation
  33. of the degradation in quality caused by the compression.
  34. \section ima_adpcm_tests_page_sec_2 How is it used?
  35. */
  36. #if defined(HAVE_CONFIG_H)
  37. #include "config.h"
  38. #endif
  39. #include <stdlib.h>
  40. #include <stdio.h>
  41. #include <fcntl.h>
  42. #include <unistd.h>
  43. #include <string.h>
  44. #include <time.h>
  45. #include <sndfile.h>
  46. #include "spandsp.h"
  47. #include "spandsp-sim.h"
  48. #define IN_FILE_NAME "../test-data/local/short_nb_voice.wav"
  49. #define OUT_FILE_NAME "post_ima_adpcm.wav"
  50. #define HIST_LEN 2000
  51. int main(int argc, char *argv[])
  52. {
  53. int i;
  54. SNDFILE *inhandle;
  55. SNDFILE *outhandle;
  56. int frames;
  57. int dec_frames;
  58. int ima_bytes;
  59. double pre_energy;
  60. double post_energy;
  61. double diff_energy;
  62. int16_t pre_amp[HIST_LEN];
  63. int16_t post_amp[HIST_LEN];
  64. uint8_t ima_data[HIST_LEN];
  65. int16_t history[HIST_LEN];
  66. int hist_in;
  67. int hist_out;
  68. ima_adpcm_state_t *ima_enc_state;
  69. ima_adpcm_state_t *ima_dec_state;
  70. int xx;
  71. int total_pre_samples;
  72. int total_compressed_bytes;
  73. int total_post_samples;
  74. int variant;
  75. int chunk_size;
  76. int enc_chunk_size;
  77. int opt;
  78. bool log_encoded_data;
  79. const char *in_file_name;
  80. variant = IMA_ADPCM_DVI4;
  81. in_file_name = IN_FILE_NAME;
  82. chunk_size = 160;
  83. enc_chunk_size = 0;
  84. log_encoded_data = false;
  85. while ((opt = getopt(argc, argv, "ac:i:lv")) != -1)
  86. {
  87. switch (opt)
  88. {
  89. case 'a':
  90. variant = IMA_ADPCM_IMA4;
  91. chunk_size = 505;
  92. break;
  93. case 'c':
  94. enc_chunk_size = atoi(optarg);
  95. break;
  96. case 'i':
  97. in_file_name = optarg;
  98. break;
  99. case 'l':
  100. log_encoded_data = true;
  101. break;
  102. case 'v':
  103. variant = IMA_ADPCM_VDVI;
  104. break;
  105. default:
  106. //usage();
  107. exit(2);
  108. break;
  109. }
  110. }
  111. if ((inhandle = sf_open_telephony_read(in_file_name, 1)) == NULL)
  112. {
  113. fprintf(stderr, " Cannot open audio file '%s'\n", in_file_name);
  114. exit(2);
  115. }
  116. if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 1)) == NULL)
  117. {
  118. fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME);
  119. exit(2);
  120. }
  121. if ((ima_enc_state = ima_adpcm_init(NULL, variant, enc_chunk_size)) == NULL)
  122. {
  123. fprintf(stderr, " Cannot create encoder\n");
  124. exit(2);
  125. }
  126. if ((ima_dec_state = ima_adpcm_init(NULL, variant, enc_chunk_size)) == NULL)
  127. {
  128. fprintf(stderr, " Cannot create decoder\n");
  129. exit(2);
  130. }
  131. hist_in = 0;
  132. hist_out = 0;
  133. pre_energy = 0.0;
  134. post_energy = 0.0;
  135. diff_energy = 0.0;
  136. total_pre_samples = 0;
  137. total_compressed_bytes = 0;
  138. total_post_samples = 0;
  139. while ((frames = sf_readf_short(inhandle, pre_amp, chunk_size)))
  140. {
  141. total_pre_samples += frames;
  142. ima_bytes = ima_adpcm_encode(ima_enc_state, ima_data, pre_amp, frames);
  143. if (log_encoded_data)
  144. write(1, ima_data, ima_bytes);
  145. total_compressed_bytes += ima_bytes;
  146. dec_frames = ima_adpcm_decode(ima_dec_state, post_amp, ima_data, ima_bytes);
  147. total_post_samples += dec_frames;
  148. for (i = 0; i < frames; i++)
  149. {
  150. history[hist_in++] = pre_amp[i];
  151. if (hist_in >= HIST_LEN)
  152. hist_in = 0;
  153. pre_energy += (double) pre_amp[i] * (double) pre_amp[i];
  154. }
  155. for (i = 0; i < dec_frames; i++)
  156. {
  157. post_energy += (double) post_amp[i] * (double) post_amp[i];
  158. xx = post_amp[i] - history[hist_out++];
  159. if (hist_out >= HIST_LEN)
  160. hist_out = 0;
  161. diff_energy += (double) xx * (double) xx;
  162. }
  163. sf_writef_short(outhandle, post_amp, dec_frames);
  164. }
  165. if (sf_close_telephony(inhandle))
  166. {
  167. fprintf(stderr, " Cannot close audio file '%s'\n", in_file_name);
  168. exit(2);
  169. }
  170. if (sf_close_telephony(outhandle))
  171. {
  172. fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
  173. exit(2);
  174. }
  175. ima_adpcm_free(ima_enc_state);
  176. ima_adpcm_free(ima_dec_state);
  177. printf("Pre samples: %d\n", total_pre_samples);
  178. printf("Compressed bytes: %d\n", total_compressed_bytes);
  179. printf("Post samples: %d\n", total_post_samples);
  180. printf("Output energy is %f%% of input energy.\n", 100.0*post_energy/pre_energy);
  181. printf("Residual energy is %f%% of the total.\n", 100.0*diff_energy/post_energy);
  182. if (fabs(1.0 - post_energy/pre_energy) > 0.05
  183. ||
  184. fabs(diff_energy/post_energy) > 0.03)
  185. {
  186. printf("Tests failed.\n");
  187. exit(2);
  188. }
  189. printf("Tests passed.\n");
  190. return 0;
  191. }
  192. /*- End of function --------------------------------------------------------*/
  193. /*- End of file ------------------------------------------------------------*/