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