ogg_opus_test.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. ** Copyright (C) 2007-2018 Erik de Castro Lopo <[email protected]>
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU General Public License as published by
  6. ** the Free Software Foundation; either version 2 of the License, or
  7. ** (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "sfconfig.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #if HAVE_UNISTD_H
  23. #include <unistd.h>
  24. #else
  25. #include "sf_unistd.h"
  26. #endif
  27. #include <math.h>
  28. #include <inttypes.h>
  29. #include <sndfile.h>
  30. #include "utils.h"
  31. #define SAMPLE_RATE 48000
  32. #define DATA_LENGTH (SAMPLE_RATE / 8)
  33. typedef union
  34. { double d [DATA_LENGTH] ;
  35. float f [DATA_LENGTH] ;
  36. int i [DATA_LENGTH] ;
  37. short s [DATA_LENGTH] ;
  38. } BUFFER ;
  39. static BUFFER data_out ;
  40. static BUFFER data_in ;
  41. static void
  42. ogg_opus_short_test (void)
  43. { const char * filename = "ogg_opus_short.opus" ;
  44. SNDFILE * file ;
  45. SF_INFO sfinfo ;
  46. short seek_data [10] ;
  47. unsigned k ;
  48. print_test_name ("ogg_opus_short_test", filename) ;
  49. /* Generate float data. */
  50. gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7F00) ;
  51. /* Convert to short. */
  52. for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++)
  53. data_out.s [k] = (short) lrintf (data_out.f [k]) ;
  54. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  55. /* Set up output file type. */
  56. sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ;
  57. sfinfo.channels = 1 ;
  58. sfinfo.samplerate = SAMPLE_RATE ;
  59. /* Write the output file. */
  60. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
  61. test_write_short_or_die (file, 0, data_out.s, ARRAY_LEN (data_out.s), __LINE__) ;
  62. sf_close (file) ;
  63. /* Read the file in again. */
  64. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  65. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  66. test_read_short_or_die (file, 0, data_in.s, ARRAY_LEN (data_in.s), __LINE__) ;
  67. sf_close (file) ;
  68. puts ("ok") ;
  69. /* Test seeking. */
  70. print_test_name ("ogg_opus_seek_test", filename) ;
  71. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  72. test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
  73. test_read_short_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
  74. compare_short_or_die (seek_data, data_in.s + 10, ARRAY_LEN (seek_data), __LINE__) ;
  75. /* Test seek to end of file. */
  76. test_seek_or_die (file, 0, SEEK_END, sfinfo.frames, sfinfo.channels, __LINE__) ;
  77. sf_close (file) ;
  78. puts ("ok") ;
  79. unlink (filename) ;
  80. } /* ogg_opus_short_test */
  81. static void
  82. ogg_opus_int_test (void)
  83. { const char * filename = "ogg_opus_int.opus" ;
  84. SNDFILE * file ;
  85. SF_INFO sfinfo ;
  86. int seek_data [10] ;
  87. unsigned k ;
  88. print_test_name ("ogg_opus_int_test", filename) ;
  89. /* Generate float data. */
  90. gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7FFF0000) ;
  91. /* Convert to integer. */
  92. for (k = 0 ; k < ARRAY_LEN (data_out.i) ; k++)
  93. data_out.i [k] = lrintf (data_out.f [k]) ;
  94. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  95. /* Set up output file type. */
  96. sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ;
  97. sfinfo.channels = 1 ;
  98. sfinfo.samplerate = SAMPLE_RATE ;
  99. /* Write the output file. */
  100. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
  101. test_write_int_or_die (file, 0, data_out.i, ARRAY_LEN (data_out.i), __LINE__) ;
  102. sf_close (file) ;
  103. /* Read the file in again. */
  104. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  105. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  106. test_read_int_or_die (file, 0, data_in.i, ARRAY_LEN (data_in.i), __LINE__) ;
  107. sf_close (file) ;
  108. puts ("ok") ;
  109. /* Test seeking. */
  110. print_test_name ("ogg_opus_seek_test", filename) ;
  111. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  112. test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
  113. test_read_int_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
  114. compare_int_or_die (seek_data, data_in.i + 10, ARRAY_LEN (seek_data), __LINE__) ;
  115. sf_close (file) ;
  116. puts ("ok") ;
  117. unlink (filename) ;
  118. } /* ogg_opus_int_test */
  119. static void
  120. ogg_opus_float_test (void)
  121. { const char * filename = "ogg_opus_float.opus" ;
  122. SNDFILE * file ;
  123. SF_INFO sfinfo ;
  124. float seek_data [10] ;
  125. print_test_name ("ogg_opus_float_test", filename) ;
  126. gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 0.95) ;
  127. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  128. /* Set up output file type. */
  129. sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ;
  130. sfinfo.channels = 1 ;
  131. sfinfo.samplerate = SAMPLE_RATE ;
  132. /* Write the output file. */
  133. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
  134. test_write_float_or_die (file, 0, data_out.f, ARRAY_LEN (data_out.f), __LINE__) ;
  135. sf_close (file) ;
  136. /* Read the file in again. */
  137. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  138. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  139. test_read_float_or_die (file, 0, data_in.f, ARRAY_LEN (data_in.f), __LINE__) ;
  140. sf_close (file) ;
  141. puts ("ok") ;
  142. /* Test seeking. */
  143. print_test_name ("ogg_opus_seek_test", filename) ;
  144. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  145. test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
  146. test_read_float_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
  147. compare_float_or_die (seek_data, data_in.f + 10, ARRAY_LEN (seek_data), __LINE__) ;
  148. sf_close (file) ;
  149. puts ("ok") ;
  150. unlink (filename) ;
  151. } /* ogg_opus_float_test */
  152. static void
  153. ogg_opus_double_test (void)
  154. { const char * filename = "ogg_opus_double.opus" ;
  155. SNDFILE * file ;
  156. SF_INFO sfinfo ;
  157. double seek_data [10] ;
  158. print_test_name ("ogg_opus_double_test", filename) ;
  159. gen_windowed_sine_double (data_out.d, ARRAY_LEN (data_out.d), 0.95) ;
  160. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  161. /* Set up output file type. */
  162. sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ;
  163. sfinfo.channels = 1 ;
  164. sfinfo.samplerate = SAMPLE_RATE ;
  165. /* Write the output file. */
  166. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
  167. test_write_double_or_die (file, 0, data_out.d, ARRAY_LEN (data_out.d), __LINE__) ;
  168. sf_close (file) ;
  169. /* Read the file in again. */
  170. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  171. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  172. test_read_double_or_die (file, 0, data_in.d, ARRAY_LEN (data_in.d), __LINE__) ;
  173. sf_close (file) ;
  174. puts ("ok") ;
  175. /* Test seeking. */
  176. print_test_name ("ogg_opus_seek_test", filename) ;
  177. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  178. test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
  179. test_read_double_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
  180. compare_double_or_die (seek_data, data_in.d + 10, ARRAY_LEN (seek_data), __LINE__) ;
  181. sf_close (file) ;
  182. puts ("ok") ;
  183. unlink (filename) ;
  184. } /* ogg_opus_double_test */
  185. static void
  186. ogg_opus_stereo_seek_test (const char * filename, int format)
  187. { static float data [SAMPLE_RATE] ;
  188. static float stereo_out [SAMPLE_RATE * 2] ;
  189. SNDFILE * file ;
  190. SF_INFO sfinfo ;
  191. sf_count_t pos ;
  192. unsigned k ;
  193. print_test_name (__func__, filename) ;
  194. gen_windowed_sine_float (data, ARRAY_LEN (data), 0.95) ;
  195. for (k = 0 ; k < ARRAY_LEN (data) ; k++)
  196. { stereo_out [2 * k] = data [k] ;
  197. stereo_out [2 * k + 1] = data [ARRAY_LEN (data) - k - 1] ;
  198. } ;
  199. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  200. /* Set up output file type. */
  201. sfinfo.format = format ;
  202. sfinfo.channels = 2 ;
  203. sfinfo.samplerate = SAMPLE_RATE ;
  204. /* Write the output file. */
  205. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
  206. test_write_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ;
  207. sf_close (file) ;
  208. /* Open file in again for reading. */
  209. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  210. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  211. /* Read in the whole file. */
  212. test_read_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ;
  213. /* Now hammer seeking code. */
  214. test_seek_or_die (file, 234, SEEK_SET, 234, sfinfo.channels, __LINE__) ;
  215. test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
  216. compare_float_or_die (data, stereo_out + (234 * sfinfo.channels), 10, __LINE__) ;
  217. test_seek_or_die (file, 442, SEEK_SET, 442, sfinfo.channels, __LINE__) ;
  218. test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
  219. compare_float_or_die (data, stereo_out + (442 * sfinfo.channels), 10, __LINE__) ;
  220. test_seek_or_die (file, 12, SEEK_CUR, 442 + 10 + 12, sfinfo.channels, __LINE__) ;
  221. test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
  222. compare_float_or_die (data, stereo_out + ((442 + 10 + 12) * sfinfo.channels), 10, __LINE__) ;
  223. test_seek_or_die (file, 12, SEEK_CUR, 442 + 20 + 24, sfinfo.channels, __LINE__) ;
  224. test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
  225. compare_float_or_die (data, stereo_out + ((442 + 20 + 24) * sfinfo.channels), 10, __LINE__) ;
  226. pos = 500 - sfinfo.frames ;
  227. test_seek_or_die (file, pos, SEEK_END, 500, sfinfo.channels, __LINE__) ;
  228. test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
  229. compare_float_or_die (data, stereo_out + (500 * sfinfo.channels), 10, __LINE__) ;
  230. pos = 10 - sfinfo.frames ;
  231. test_seek_or_die (file, pos, SEEK_END, 10, sfinfo.channels, __LINE__) ;
  232. test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
  233. compare_float_or_die (data, stereo_out + (10 * sfinfo.channels), 10, __LINE__) ;
  234. sf_close (file) ;
  235. puts ("ok") ;
  236. unlink (filename) ;
  237. } /* ogg_opus_stereo_seek_test */
  238. static void
  239. ogg_opus_original_samplerate_test (void)
  240. { const char * filename = "ogg_opus_original_samplerate.opus" ;
  241. SNDFILE * file ;
  242. SF_INFO sfinfo ;
  243. int original_samplerate = 54321 ;
  244. sf_count_t frames ;
  245. print_test_name ("ogg_opus_original_samplerate_test", filename) ;
  246. gen_windowed_sine_double (data_out.d, ARRAY_LEN (data_out.d), 0.95) ;
  247. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  248. /* Set up output file type. */
  249. sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ;
  250. sfinfo.channels = 1 ;
  251. sfinfo.samplerate = SAMPLE_RATE ;
  252. /* Write the output file. */
  253. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
  254. if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_TRUE)
  255. { printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE failed!\n") ;
  256. exit (1) ;
  257. } ;
  258. test_write_double_or_die (file, 0, data_out.d, ARRAY_LEN (data_out.d), __LINE__) ;
  259. if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_FALSE)
  260. { printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE succeeded when it should have failed!") ;
  261. exit (1) ;
  262. } ;
  263. sf_close (file) ;
  264. /* Read the file in again. */
  265. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  266. original_samplerate = 0 ;
  267. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  268. if (sf_command (file, SFC_GET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_TRUE
  269. || original_samplerate != 54321)
  270. { printf ("\nCommand SFC_GET_ORIGINAL_SAMPLERATE failed!\n") ;
  271. exit (1) ;
  272. } ;
  273. test_read_double_or_die (file, 0, data_in.d, 8, __LINE__) ;
  274. if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) == SF_TRUE)
  275. { printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE succeeded when it should have failed!\n") ;
  276. exit (1) ;
  277. } ;
  278. sf_close (file) ;
  279. /* Test changing the decoder. */
  280. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  281. frames = sfinfo.frames ;
  282. original_samplerate = 16000 ;
  283. if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_TRUE)
  284. { printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE failed!\n") ;
  285. exit (1) ;
  286. } ;
  287. if (sf_command (file, SFC_GET_CURRENT_SF_INFO, &sfinfo, sizeof (sfinfo)))
  288. { printf ("\nCommand SFC_GET_CURRENT_SF_INFO failed!\n") ;
  289. exit (1) ;
  290. } ;
  291. if (frames / (48000 / 16000) != sfinfo.frames)
  292. { printf ("\nIncorrect frame count! (%" PRId64 " vs %" PRId64")\n", frames / (48000 / 16000), sfinfo.frames) ;
  293. exit (1) ;
  294. } ;
  295. test_read_double_or_die (file, 0, data_out.d, sfinfo.frames, __LINE__) ;
  296. sf_close (file) ;
  297. puts ("ok") ;
  298. unlink (filename) ;
  299. } /* ogg_opus_original_samplerate_test */
  300. int
  301. main (void)
  302. {
  303. if (HAVE_EXTERNAL_XIPH_LIBS)
  304. { ogg_opus_short_test () ;
  305. ogg_opus_int_test () ;
  306. ogg_opus_float_test () ;
  307. ogg_opus_double_test () ;
  308. ogg_opus_stereo_seek_test ("ogg_opus_seek.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS) ;
  309. ogg_opus_original_samplerate_test () ;
  310. }
  311. else
  312. puts (" No Ogg/Opus tests because Ogg/Opus support was not compiled in.") ;
  313. return 0 ;
  314. } /* main */