xref: /third_party/libsnd/tests/mpeg_test.c (revision b815c7f3)
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