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.

234 lines
5.9KB

  1. /*
  2. ** Copyright (c) 2003-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 <string.h>
  11. #include <math.h>
  12. #include <samplerate.h>
  13. #include "util.h"
  14. #define BUFFER_LEN 10000
  15. #define CB_READ_LEN 256
  16. static void callback_test (int converter, double ratio) ;
  17. static void end_of_stream_test (int converter) ;
  18. int
  19. main (void)
  20. { static double src_ratios [] =
  21. { 1.0, 0.099, 0.1, 0.33333333, 0.789, 1.0001, 1.9, 3.1, 9.9
  22. } ;
  23. int k ;
  24. puts ("") ;
  25. puts (" Zero Order Hold interpolator :") ;
  26. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  27. callback_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
  28. puts (" Linear interpolator :") ;
  29. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  30. callback_test (SRC_LINEAR, src_ratios [k]) ;
  31. puts (" Sinc interpolator :") ;
  32. for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
  33. callback_test (SRC_SINC_FASTEST, src_ratios [k]) ;
  34. puts ("") ;
  35. puts (" End of stream test :") ;
  36. end_of_stream_test (SRC_ZERO_ORDER_HOLD) ;
  37. end_of_stream_test (SRC_LINEAR) ;
  38. end_of_stream_test (SRC_SINC_FASTEST) ;
  39. puts ("") ;
  40. return 0 ;
  41. } /* main */
  42. /*=====================================================================================
  43. */
  44. typedef struct
  45. { int channels ;
  46. long count, total ;
  47. int end_of_data ;
  48. float data [BUFFER_LEN] ;
  49. } TEST_CB_DATA ;
  50. static long
  51. test_callback_func (void *cb_data, float **data)
  52. { TEST_CB_DATA *pcb_data ;
  53. long frames ;
  54. if ((pcb_data = cb_data) == NULL)
  55. return 0 ;
  56. if (data == NULL)
  57. return 0 ;
  58. if (pcb_data->total - pcb_data->count > CB_READ_LEN)
  59. frames = CB_READ_LEN / pcb_data->channels ;
  60. else
  61. frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ;
  62. *data = pcb_data->data + pcb_data->count ;
  63. pcb_data->count += frames ;
  64. return frames ;
  65. } /* test_callback_func */
  66. static void
  67. callback_test (int converter, double src_ratio)
  68. { static TEST_CB_DATA test_callback_data ;
  69. static float output [BUFFER_LEN] ;
  70. SRC_STATE *src_state ;
  71. long read_count, read_total ;
  72. int error ;
  73. printf ("\tcallback_test (SRC ratio = %6.4f) ........... ", src_ratio) ;
  74. fflush (stdout) ;
  75. test_callback_data.channels = 2 ;
  76. test_callback_data.count = 0 ;
  77. test_callback_data.end_of_data = 0 ;
  78. test_callback_data.total = ARRAY_LEN (test_callback_data.data) ;
  79. if ((src_state = src_callback_new (test_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL)
  80. { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
  81. exit (1) ;
  82. } ;
  83. read_total = 0 ;
  84. do
  85. { /* We will be throwing away output data, so just grab as much as possible. */
  86. read_count = ARRAY_LEN (output) / test_callback_data.channels ;
  87. read_count = src_callback_read (src_state, src_ratio, read_count, output) ;
  88. read_total += read_count ;
  89. }
  90. while (read_count > 0) ;
  91. if ((error = src_error (src_state)) != 0)
  92. { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
  93. exit (1) ;
  94. } ;
  95. src_state = src_delete (src_state) ;
  96. if (fabs (read_total / src_ratio - ARRAY_LEN (test_callback_data.data)) > 2.0)
  97. { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
  98. printf (" input len : %d\n", ARRAY_LEN (test_callback_data.data)) ;
  99. printf (" output len : %ld (should be %g +/- 2)\n\n", read_total,
  100. floor (0.5 + src_ratio * ARRAY_LEN (test_callback_data.data))) ;
  101. exit (1) ;
  102. } ;
  103. puts ("ok") ;
  104. return ;
  105. } /* callback_test */
  106. /*=====================================================================================
  107. */
  108. static long
  109. eos_callback_func (void *cb_data, float **data)
  110. {
  111. TEST_CB_DATA *pcb_data ;
  112. long frames ;
  113. if (data == NULL)
  114. return 0 ;
  115. if ((pcb_data = cb_data) == NULL)
  116. return 0 ;
  117. /*
  118. ** Return immediately if there is no more data.
  119. ** In this case, the output pointer 'data' will not be set and
  120. ** valgrind should not warn about it.
  121. */
  122. if (pcb_data->end_of_data)
  123. return 0 ;
  124. if (pcb_data->total - pcb_data->count > CB_READ_LEN)
  125. frames = CB_READ_LEN / pcb_data->channels ;
  126. else
  127. frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ;
  128. *data = pcb_data->data + pcb_data->count ;
  129. pcb_data->count += frames ;
  130. /*
  131. ** Set end_of_data so that the next call to the callback function will
  132. ** return zero ocunt without setting the 'data' pointer.
  133. */
  134. if (pcb_data->total < 2 * pcb_data->count)
  135. pcb_data->end_of_data = 1 ;
  136. return frames ;
  137. } /* eos_callback_data */
  138. static void
  139. end_of_stream_test (int converter)
  140. { static TEST_CB_DATA test_callback_data ;
  141. static float output [BUFFER_LEN] ;
  142. SRC_STATE *src_state ;
  143. double src_ratio = 0.3 ;
  144. long read_count, read_total ;
  145. int error ;
  146. printf ("\t%-30s ........... ", src_get_name (converter)) ;
  147. fflush (stdout) ;
  148. test_callback_data.channels = 2 ;
  149. test_callback_data.count = 0 ;
  150. test_callback_data.end_of_data = 0 ;
  151. test_callback_data.total = ARRAY_LEN (test_callback_data.data) ;
  152. if ((src_state = src_callback_new (eos_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL)
  153. { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
  154. exit (1) ;
  155. } ;
  156. read_total = 0 ;
  157. do
  158. { /* We will be throwing away output data, so just grab as much as possible. */
  159. read_count = ARRAY_LEN (output) / test_callback_data.channels ;
  160. read_count = src_callback_read (src_state, src_ratio, read_count, output) ;
  161. read_total += read_count ;
  162. }
  163. while (read_count > 0) ;
  164. if ((error = src_error (src_state)) != 0)
  165. { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
  166. exit (1) ;
  167. } ;
  168. src_state = src_delete (src_state) ;
  169. if (test_callback_data.end_of_data == 0)
  170. { printf ("\n\nLine %d : test_callback_data.end_of_data should not be 0."
  171. " This is a bug in the test.\n\n", __LINE__) ;
  172. exit (1) ;
  173. } ;
  174. puts ("ok") ;
  175. return ;
  176. } /* end_of_stream_test */