1 /*
2 ** Copyright (C) 2007-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
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
19 #include "sfconfig.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #else
27 #include "sf_unistd.h"
28 #endif
29
30 #include <math.h>
31
32 #include <sndfile.h>
33
34 #include "utils.h"
35
36 #define SAMPLE_RATE 44100
37 #define DATA_LENGTH (SAMPLE_RATE / 8)
38
39 typedef union
40 { double d [DATA_LENGTH] ;
41 float f [DATA_LENGTH] ;
42 int i [DATA_LENGTH] ;
43 short s [DATA_LENGTH] ;
44 } BUFFER ;
45
46 static BUFFER data_out ;
47 static BUFFER data_in ;
48
49 static void
ogg_short_test(void)50 ogg_short_test (void)
51 { const char * filename = "vorbis_short.oga" ;
52
53 SNDFILE * file ;
54 SF_INFO sfinfo ;
55 short seek_data [10] ;
56 unsigned k ;
57
58 print_test_name ("ogg_short_test", filename) ;
59
60 /* Generate float data. */
61 gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7F00) ;
62
63 /* Convert to shorteger. */
64 for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++)
65 data_out.s [k] = lrintf (data_out.f [k]) ;
66
67 memset (&sfinfo, 0, sizeof (sfinfo)) ;
68
69 /* Set up output file type. */
70 sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
71 sfinfo.channels = 1 ;
72 sfinfo.samplerate = SAMPLE_RATE ;
73
74 /* Write the output file. */
75 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
76 test_write_short_or_die (file, 0, data_out.s, ARRAY_LEN (data_out.s), __LINE__) ;
77 sf_close (file) ;
78
79 /* Read the file in again. */
80 memset (&sfinfo, 0, sizeof (sfinfo)) ;
81
82 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
83 test_read_short_or_die (file, 0, data_in.s, ARRAY_LEN (data_in.s), __LINE__) ;
84 sf_close (file) ;
85
86 puts ("ok") ;
87
88 /* Test seeking. */
89 print_test_name ("ogg_seek_test", filename) ;
90
91 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
92
93 test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
94 test_read_short_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
95 compare_short_or_die (seek_data, data_in.s + 10, ARRAY_LEN (seek_data), __LINE__) ;
96
97 /* Test seek to end of file. */
98 test_seek_or_die (file, 0, SEEK_END, sfinfo.frames, sfinfo.channels, __LINE__) ;
99
100 sf_close (file) ;
101
102 puts ("ok") ;
103
104 unlink (filename) ;
105 } /* ogg_short_test */
106
107 static void
ogg_int_test(void)108 ogg_int_test (void)
109 { const char * filename = "vorbis_int.oga" ;
110
111 SNDFILE * file ;
112 SF_INFO sfinfo ;
113 int seek_data [10] ;
114 unsigned k ;
115
116 print_test_name ("ogg_int_test", filename) ;
117
118 /* Generate float data. */
119 gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7FFF0000) ;
120
121 /* Convert to integer. */
122 for (k = 0 ; k < ARRAY_LEN (data_out.i) ; k++)
123 data_out.i [k] = lrintf (data_out.f [k]) ;
124
125 memset (&sfinfo, 0, sizeof (sfinfo)) ;
126
127 /* Set up output file type. */
128 sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
129 sfinfo.channels = 1 ;
130 sfinfo.samplerate = SAMPLE_RATE ;
131
132 /* Write the output file. */
133 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
134 test_write_int_or_die (file, 0, data_out.i, ARRAY_LEN (data_out.i), __LINE__) ;
135 sf_close (file) ;
136
137 /* Read the file in again. */
138 memset (&sfinfo, 0, sizeof (sfinfo)) ;
139
140 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
141 test_read_int_or_die (file, 0, data_in.i, ARRAY_LEN (data_in.i), __LINE__) ;
142 sf_close (file) ;
143
144 puts ("ok") ;
145
146 /* Test seeking. */
147 print_test_name ("ogg_seek_test", filename) ;
148
149 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
150
151 test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
152 test_read_int_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
153 compare_int_or_die (seek_data, data_in.i + 10, ARRAY_LEN (seek_data), __LINE__) ;
154
155 sf_close (file) ;
156
157 puts ("ok") ;
158
159 unlink (filename) ;
160 } /* ogg_int_test */
161
162 static void
ogg_float_test(void)163 ogg_float_test (void)
164 { const char * filename = "vorbis_float.oga" ;
165
166 SNDFILE * file ;
167 SF_INFO sfinfo ;
168 float seek_data [10] ;
169
170 print_test_name ("ogg_float_test", filename) ;
171
172 gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 0.95) ;
173
174 memset (&sfinfo, 0, sizeof (sfinfo)) ;
175
176 /* Set up output file type. */
177 sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
178 sfinfo.channels = 1 ;
179 sfinfo.samplerate = SAMPLE_RATE ;
180
181 /* Write the output file. */
182 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
183 test_write_float_or_die (file, 0, data_out.f, ARRAY_LEN (data_out.f), __LINE__) ;
184 sf_close (file) ;
185
186 /* Read the file in again. */
187 memset (&sfinfo, 0, sizeof (sfinfo)) ;
188
189 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
190 test_read_float_or_die (file, 0, data_in.f, ARRAY_LEN (data_in.f), __LINE__) ;
191 sf_close (file) ;
192
193 puts ("ok") ;
194
195 /* Test seeking. */
196 print_test_name ("ogg_seek_test", filename) ;
197
198 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
199
200 test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
201 test_read_float_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
202 compare_float_or_die (seek_data, data_in.f + 10, ARRAY_LEN (seek_data), __LINE__) ;
203
204 sf_close (file) ;
205
206 puts ("ok") ;
207
208 unlink (filename) ;
209 } /* ogg_float_test */
210
211 static void
ogg_double_test(void)212 ogg_double_test (void)
213 { const char * filename = "vorbis_double.oga" ;
214
215 SNDFILE * file ;
216 SF_INFO sfinfo ;
217 double seek_data [10] ;
218
219 print_test_name ("ogg_double_test", filename) ;
220
221 gen_windowed_sine_double (data_out.d, ARRAY_LEN (data_out.d), 0.95) ;
222
223 memset (&sfinfo, 0, sizeof (sfinfo)) ;
224
225 /* Set up output file type. */
226 sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
227 sfinfo.channels = 1 ;
228 sfinfo.samplerate = SAMPLE_RATE ;
229
230 /* Write the output file. */
231 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
232 test_write_double_or_die (file, 0, data_out.d, ARRAY_LEN (data_out.d), __LINE__) ;
233 sf_close (file) ;
234
235 /* Read the file in again. */
236 memset (&sfinfo, 0, sizeof (sfinfo)) ;
237
238 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
239 test_read_double_or_die (file, 0, data_in.d, ARRAY_LEN (data_in.d), __LINE__) ;
240 sf_close (file) ;
241
242 puts ("ok") ;
243
244 /* Test seeking. */
245 print_test_name ("ogg_seek_test", filename) ;
246
247 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
248
249 test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
250 test_read_double_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
251 compare_double_or_die (seek_data, data_in.d + 10, ARRAY_LEN (seek_data), __LINE__) ;
252
253 sf_close (file) ;
254
255 puts ("ok") ;
256
257 unlink (filename) ;
258 } /* ogg_double_test */
259
260
261 static void
ogg_stereo_seek_test(const char * filename,int format)262 ogg_stereo_seek_test (const char * filename, int format)
263 { static float data [SAMPLE_RATE] ;
264 static float stereo_out [SAMPLE_RATE * 2] ;
265
266 SNDFILE * file ;
267 SF_INFO sfinfo ;
268 sf_count_t pos ;
269 unsigned k ;
270
271 print_test_name (__func__, filename) ;
272
273 gen_windowed_sine_float (data, ARRAY_LEN (data), 0.95) ;
274 for (k = 0 ; k < ARRAY_LEN (data) ; k++)
275 { stereo_out [2 * k] = data [k] ;
276 stereo_out [2 * k + 1] = data [ARRAY_LEN (data) - k - 1] ;
277 } ;
278
279 memset (&sfinfo, 0, sizeof (sfinfo)) ;
280
281 /* Set up output file type. */
282 sfinfo.format = format ;
283 sfinfo.channels = 2 ;
284 sfinfo.samplerate = SAMPLE_RATE ;
285
286 /* Write the output file. */
287 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
288 test_write_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ;
289 sf_close (file) ;
290
291 /* Open file in again for reading. */
292 memset (&sfinfo, 0, sizeof (sfinfo)) ;
293 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
294
295 /* Read in the whole file. */
296 test_read_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ;
297
298 /* Now hammer seeking code. */
299 test_seek_or_die (file, 234, SEEK_SET, 234, sfinfo.channels, __LINE__) ;
300 test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
301 compare_float_or_die (data, stereo_out + (234 * sfinfo.channels), 10, __LINE__) ;
302
303 test_seek_or_die (file, 442, SEEK_SET, 442, sfinfo.channels, __LINE__) ;
304 test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
305 compare_float_or_die (data, stereo_out + (442 * sfinfo.channels), 10, __LINE__) ;
306
307 test_seek_or_die (file, 12, SEEK_CUR, 442 + 10 + 12, sfinfo.channels, __LINE__) ;
308 test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
309 compare_float_or_die (data, stereo_out + ((442 + 10 + 12) * sfinfo.channels), 10, __LINE__) ;
310
311 test_seek_or_die (file, 12, SEEK_CUR, 442 + 20 + 24, sfinfo.channels, __LINE__) ;
312 test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
313 compare_float_or_die (data, stereo_out + ((442 + 20 + 24) * sfinfo.channels), 10, __LINE__) ;
314
315 pos = 500 - sfinfo.frames ;
316 test_seek_or_die (file, pos, SEEK_END, 500, sfinfo.channels, __LINE__) ;
317 test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
318 compare_float_or_die (data, stereo_out + (500 * sfinfo.channels), 10, __LINE__) ;
319
320 pos = 10 - sfinfo.frames ;
321 test_seek_or_die (file, pos, SEEK_END, 10, sfinfo.channels, __LINE__) ;
322 test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
323 compare_float_or_die (data, stereo_out + (10 * sfinfo.channels), 10, __LINE__) ;
324
325 sf_close (file) ;
326
327 puts ("ok") ;
328 unlink (filename) ;
329 } /* ogg_stereo_seek_test */
330
331
332 int
main(void)333 main (void)
334 {
335 if (HAVE_EXTERNAL_XIPH_LIBS)
336 { ogg_short_test () ;
337 ogg_int_test () ;
338 ogg_float_test () ;
339 ogg_double_test () ;
340
341 /*-ogg_stereo_seek_test ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;-*/
342 ogg_stereo_seek_test ("vorbis_seek.ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS) ;
343 }
344 else
345 puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
346
347 return 0 ;
348 } /* main */
349