You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
9.2KB

  1. /*
  2. ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
  3. ** All rights reserved.
  4. **
  5. ** This code is released under 2-clause BSD license. Please see the
  6. ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11. #include <samplerate.h>
  12. #include "util.h"
  13. #define SHORT_BUFFER_LEN 2048
  14. #define LONG_BUFFER_LEN ((1 << 16) - 20)
  15. static void simple_test (int converter) ;
  16. static void stream_test (int converter, double ratio) ;
  17. static void init_term_test (int converter, double ratio) ;
  18. static int next_block_length (int reset) ;
  19. int
  20. main (void)
  21. { static double src_ratios [] =
  22. { 0.999900, 1.000100, 0.789012, 1.200000, 0.333333, 3.100000,
  23. 0.125000, 8.000000, 0.099900, 9.990000, 0.100000, 10.00000
  24. } ;
  25. int k ;
  26. puts ("\n Zero Order Hold interpolator:") ;
  27. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  28. init_term_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
  29. puts ("") ;
  30. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  31. stream_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
  32. puts ("\n Linear interpolator:") ;
  33. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  34. init_term_test (SRC_LINEAR, src_ratios [k]) ;
  35. puts ("") ;
  36. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  37. stream_test (SRC_LINEAR, src_ratios [k]) ;
  38. puts ("\n Sinc interpolator:") ;
  39. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  40. init_term_test (SRC_SINC_FASTEST, src_ratios [k]) ;
  41. puts ("") ;
  42. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  43. stream_test (SRC_SINC_FASTEST, src_ratios [k]) ;
  44. puts ("") ;
  45. simple_test (SRC_SINC_FASTEST) ;
  46. return 0 ;
  47. } /* main */
  48. static void
  49. simple_test (int converter)
  50. {
  51. int ilen = 199030, olen = 1000, error ;
  52. {
  53. float in [ilen] ;
  54. float out [olen] ;
  55. double ratio = (1.0 * olen) / ilen ;
  56. SRC_DATA src_data =
  57. { in, out,
  58. ilen, olen,
  59. 0, 0, 0,
  60. ratio
  61. } ;
  62. error = src_simple (&src_data, converter, 1) ;
  63. if (error)
  64. { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
  65. exit (1) ;
  66. } ;
  67. } ;
  68. return ;
  69. } /* simple_test */
  70. static void
  71. init_term_test (int converter, double src_ratio)
  72. { static float input [SHORT_BUFFER_LEN], output [SHORT_BUFFER_LEN] ;
  73. SRC_DATA src_data ;
  74. int k, input_len, output_len, error, terminate ;
  75. printf ("\tinit_term_test (SRC ratio = %7.4f) .......... ", src_ratio) ;
  76. fflush (stdout) ;
  77. /* Calculate maximun input and output lengths. */
  78. if (src_ratio >= 1.0)
  79. { output_len = SHORT_BUFFER_LEN ;
  80. input_len = (int) floor (SHORT_BUFFER_LEN / src_ratio) ;
  81. }
  82. else
  83. { input_len = SHORT_BUFFER_LEN ;
  84. output_len = (int) floor (SHORT_BUFFER_LEN * src_ratio) ;
  85. } ;
  86. /* Reduce input_len by 10 so output is longer than necessary. */
  87. input_len -= 10 ;
  88. for (k = 0 ; k < ARRAY_LEN (input) ; k++)
  89. input [k] = 1.0 ;
  90. if (output_len > SHORT_BUFFER_LEN)
  91. { printf ("\n\nLine %d : output_len > SHORT_BUFFER_LEN\n\n", __LINE__) ;
  92. exit (1) ;
  93. } ;
  94. src_data.data_in = input ;
  95. src_data.input_frames = input_len ;
  96. src_data.src_ratio = src_ratio ;
  97. src_data.data_out = output ;
  98. src_data.output_frames = SHORT_BUFFER_LEN ;
  99. if ((error = src_simple (&src_data, converter, 1)))
  100. { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
  101. exit (1) ;
  102. } ;
  103. terminate = (int) ceil ((src_ratio >= 1.0) ? 1 : 1.0 / src_ratio) ;
  104. if (fabs (src_ratio * input_len - src_data.output_frames_gen) > terminate)
  105. { printf ("\n\nLine %d : Bad output frame count.\n\n", __LINE__) ;
  106. printf ("\tterminate : %d\n", terminate) ;
  107. printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
  108. printf ("\tinput_len : %d\n"
  109. "\tinput_len * src_ratio : %f\n", input_len, input_len * src_ratio) ;
  110. printf ("\toutput_frames_gen : %ld\n\n", src_data.output_frames_gen) ;
  111. exit (1) ;
  112. } ;
  113. if (labs (src_data.input_frames_used - input_len) > 1)
  114. { printf ("\n\nLine %d : input_frames_used should be %d, is %ld.\n\n",
  115. __LINE__, input_len, src_data.input_frames_used) ;
  116. printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
  117. printf ("\tinput_len : %d\n\tinput_used : %ld\n\n", input_len, src_data.input_frames_used) ;
  118. exit (1) ;
  119. } ;
  120. if (fabs (output [0]) < 0.1)
  121. { printf ("\n\nLine %d : First output sample is bad.\n\n", __LINE__) ;
  122. printf ("\toutput [0] == %f\n\n", output [0]) ;
  123. exit (1) ;
  124. }
  125. puts ("ok") ;
  126. return ;
  127. } /* init_term_test */
  128. static void
  129. stream_test (int converter, double src_ratio)
  130. { static float input [LONG_BUFFER_LEN], output [LONG_BUFFER_LEN] ;
  131. SRC_STATE *src_state ;
  132. SRC_DATA src_data ;
  133. int input_len, output_len, current_in, current_out ;
  134. int k, error, terminate ;
  135. printf ("\tstream_test (SRC ratio = %7.4f) .......... ", src_ratio) ;
  136. fflush (stdout) ;
  137. /* Erik */
  138. for (k = 0 ; k < LONG_BUFFER_LEN ; k++) input [k] = k * 1.0 ;
  139. /* Calculate maximun input and output lengths. */
  140. if (src_ratio >= 1.0)
  141. { output_len = LONG_BUFFER_LEN ;
  142. input_len = (int) floor (LONG_BUFFER_LEN / src_ratio) ;
  143. }
  144. else
  145. { input_len = LONG_BUFFER_LEN ;
  146. output_len = (int) floor (LONG_BUFFER_LEN * src_ratio) ;
  147. } ;
  148. /* Reduce input_len by 10 so output is longer than necessary. */
  149. input_len -= 20 ;
  150. if (output_len > LONG_BUFFER_LEN)
  151. { printf ("\n\nLine %d : output_len > LONG_BUFFER_LEN\n\n", __LINE__) ;
  152. exit (1) ;
  153. } ;
  154. current_in = current_out = 0 ;
  155. /* Perform sample rate conversion. */
  156. if ((src_state = src_new (converter, 1, &error)) == NULL)
  157. { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
  158. exit (1) ;
  159. } ;
  160. src_data.end_of_input = 0 ; /* Set this later. */
  161. src_data.data_in = input ;
  162. src_data.src_ratio = src_ratio ;
  163. src_data.data_out = output ;
  164. src_data.output_frames = ARRAY_LEN (output) / 10 ;
  165. terminate = 1 + (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ;
  166. while (1)
  167. {
  168. src_data.input_frames = next_block_length (0) ;
  169. src_data.input_frames = MIN (src_data.input_frames, input_len - current_in) ;
  170. src_data.output_frames = ARRAY_LEN (output) - current_out ;
  171. /*-Erik MIN (src_data.output_frames, output_len - current_out) ;-*/
  172. src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ;
  173. if ((error = src_process (src_state, &src_data)))
  174. { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
  175. printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
  176. printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ;
  177. exit (1) ;
  178. } ;
  179. if (src_data.end_of_input && src_data.output_frames_gen == 0)
  180. break ;
  181. if (src_data.input_frames_used > src_data.input_frames)
  182. { printf ("\n\nLine %d : input_frames_used > input_frames\n\n", __LINE__) ;
  183. printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
  184. printf (" src_data.input_frames_used : %ld\n", src_data.input_frames_used) ;
  185. printf (" src_data.output_frames : %ld\n", src_data.output_frames) ;
  186. printf (" src_data.output_frames_gen : %ld\n\n", src_data.output_frames_gen) ;
  187. exit (1) ;
  188. } ;
  189. if (src_data.input_frames_used < 0)
  190. { printf ("\n\nLine %d : input_frames_used (%ld) < 0\n\n", __LINE__, src_data.input_frames_used) ;
  191. exit (1) ;
  192. } ;
  193. if (src_data.output_frames_gen < 0)
  194. { printf ("\n\nLine %d : output_frames_gen (%ld) < 0\n\n", __LINE__, src_data.output_frames_gen) ;
  195. exit (1) ;
  196. } ;
  197. current_in += src_data.input_frames_used ;
  198. current_out += src_data.output_frames_gen ;
  199. if (current_in > input_len + terminate)
  200. { printf ("\n\nLine %d : current_in (%d) > input_len (%d + %d)\n\n", __LINE__, current_in, input_len, terminate) ;
  201. exit (1) ;
  202. } ;
  203. if (current_out > output_len)
  204. { printf ("\n\nLine %d : current_out (%d) > output_len (%d)\n\n", __LINE__, current_out, output_len) ;
  205. exit (1) ;
  206. } ;
  207. if (src_data.input_frames_used > input_len)
  208. { printf ("\n\nLine %d : input_frames_used (%ld) > %d\n\n", __LINE__, src_data.input_frames_used, input_len) ;
  209. exit (1) ;
  210. } ;
  211. if (src_data.output_frames_gen > output_len)
  212. { printf ("\n\nLine %d : output_frames_gen (%ld) > %d\n\n", __LINE__, src_data.output_frames_gen, output_len) ;
  213. exit (1) ;
  214. } ;
  215. if (src_data.data_in == NULL && src_data.output_frames_gen == 0)
  216. break ;
  217. src_data.data_in += src_data.input_frames_used ;
  218. src_data.data_out += src_data.output_frames_gen ;
  219. } ;
  220. src_state = src_delete (src_state) ;
  221. if (fabs (current_out - src_ratio * input_len) > terminate)
  222. { printf ("\n\nLine %d : bad output data length %d should be %2.1f +/- %d.\n", __LINE__,
  223. current_out, src_ratio * input_len, terminate) ;
  224. printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
  225. printf ("\tinput_len : %d\n\tinput_used : %d\n", input_len, current_in) ;
  226. printf ("\toutput_len : %d\n\toutput_gen : %d\n\n", output_len, current_out) ;
  227. exit (1) ;
  228. } ;
  229. if (current_in != input_len)
  230. { printf ("\n\nLine %d : unused input.\n", __LINE__) ;
  231. printf ("\tinput_len : %d\n", input_len) ;
  232. printf ("\tinput_frames_used : %d\n\n", current_in) ;
  233. exit (1) ;
  234. } ;
  235. puts ("ok") ;
  236. return ;
  237. } /* stream_test */
  238. static int
  239. next_block_length (int reset)
  240. { static int block_lengths [] = /* Should be an odd length. */
  241. { /*-2, 500, 5, 400, 10, 300, 20, 200, 50, 100, 70 -*/
  242. 5, 400, 10, 300, 20, 200, 50, 100, 70
  243. } ;
  244. static int block_len_index = 0 ;
  245. if (reset)
  246. block_len_index = 0 ;
  247. else
  248. block_len_index = (block_len_index + 1) % ARRAY_LEN (block_lengths) ;
  249. return block_lengths [block_len_index] ;
  250. } /* next_block_length */