xref: /third_party/libsnd/tests/ulaw_test.c (revision b815c7f3)
1/*
2** Copyright (C) 1999-2012 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
25#if HAVE_UNISTD_H
26#include <unistd.h>
27#else
28#include "sf_unistd.h"
29#endif
30
31#include <sndfile.h>
32
33#include "utils.h"
34
35#define	BUFFER_SIZE		(65536)
36
37static unsigned char	ulaw_encode (int sample) ;
38static int				ulaw_decode (unsigned int ulawbyte) ;
39
40static	short			short_buffer [BUFFER_SIZE] ;
41static	unsigned char	ulaw_buffer [BUFFER_SIZE] ;
42
43int
44main (void)
45{	SNDFILE		*file ;
46	SF_INFO 	sfinfo ;
47	const char	*filename ;
48	int			k ;
49
50	print_test_name ("ulaw_test", "encoder") ;
51
52	filename = "ulaw_test.raw" ;
53
54	sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ULAW, 44100, 1) ;
55
56	if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
57	{	printf ("sf_open_write failed with error : ") ;
58		fflush (stdout) ;
59		puts (sf_strerror (NULL)) ;
60		exit (1) ;
61		} ;
62
63	/* Generate a file containing all possible 16 bit sample values
64	** and write it to disk as ulaw encoded.frames.
65	*/
66
67	for (k = 0 ; k < 0x10000 ; k++)
68		short_buffer [k] = k & 0xFFFF ;
69
70	sf_write_short (file, short_buffer, BUFFER_SIZE) ;
71	sf_close (file) ;
72
73	/* Now open that file and compare the ulaw encoded sample values
74	** with what they should be.
75	*/
76
77	if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
78	{	printf ("sf_open_write failed with error : ") ;
79		puts (sf_strerror (NULL)) ;
80		exit (1) ;
81		} ;
82
83	check_log_buffer_or_die (file, __LINE__) ;
84
85	if (sf_read_raw (file, ulaw_buffer, BUFFER_SIZE) != BUFFER_SIZE)
86	{	printf ("sf_read_raw : ") ;
87		puts (sf_strerror (file)) ;
88		exit (1) ;
89		} ;
90
91	for (k = 0 ; k < 0x10000 ; k++)
92		if (ulaw_encode (short_buffer [k]) != ulaw_buffer [k])
93		{	printf ("Encoder error : sample #%d (0x%02X should be 0x%02X)\n", k, ulaw_buffer [k], ulaw_encode (short_buffer [k])) ;
94			exit (1) ;
95			} ;
96
97	sf_close (file) ;
98
99	puts ("ok") ;
100
101	print_test_name ("ulaw_test", "decoder") ;
102
103	/* Now generate a file containing all possible 8 bit encoded
104	** sample values and write it to disk as ulaw encoded.frames.
105	*/
106
107	if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
108	{	printf ("sf_open_write failed with error : ") ;
109		puts (sf_strerror (NULL)) ;
110		exit (1) ;
111		} ;
112
113	for (k = 0 ; k < 256 ; k++)
114		ulaw_buffer [k] = k & 0xFF ;
115
116	sf_write_raw (file, ulaw_buffer, 256) ;
117	sf_close (file) ;
118
119	/* Now open that file and compare the ulaw decoded sample values
120	** with what they should be.
121	*/
122
123	if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
124	{	printf ("sf_open_write failed with error : ") ;
125		puts (sf_strerror (NULL)) ;
126		exit (1) ;
127		} ;
128
129	check_log_buffer_or_die (file, __LINE__) ;
130
131	if (sf_read_short (file, short_buffer, 256) != 256)
132	{	printf ("sf_read_short : ") ;
133		puts (sf_strerror (file)) ;
134		exit (1) ;
135		} ;
136
137
138	for (k = 0 ; k < 256 ; k++)
139		if (short_buffer [k] != ulaw_decode (ulaw_buffer [k]))
140		{	printf ("Decoder error : sample #%d (0x%04X should be 0x%04X)\n", k, short_buffer [k], ulaw_decode (ulaw_buffer [k])) ;
141			exit (1) ;
142			} ;
143
144	sf_close (file) ;
145
146	puts ("ok") ;
147
148	unlink (filename) ;
149
150	return 0 ;
151} /* main */
152
153
154/*=================================================================================
155**	The following routines came from the sox-12.15 (Sound eXcahcnge) distribution.
156**
157**	This code is not compiled into libsndfile. It is only used to test the
158**	libsndfile lookup tables for correctness.
159**
160**	I have included the original authors comments.
161*/
162
163/*
164** This routine converts from linear to ulaw.
165**
166** Craig Reese: IDA/Supercomputing Research Center
167** Joe Campbell: Department of Defense
168** 29 September 1989
169**
170** References:
171** 1) CCITT Recommendation G.711  (very difficult to follow)
172** 2) "A New Digital Technique for Implementation of Any
173**     Continuous PCM Companding Law," Villeret, Michel,
174**     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
175**     1973, pg. 11.12-11.17
176** 3) MIL-STD-188-113,"Interoperability and Performance Standards
177**     for Analog-to_Digital Conversion Techniques,"
178**     17 February 1987
179**
180** Input: Signed 16 bit linear sample
181** Output: 8 bit ulaw sample
182*/
183
184#define uBIAS 0x84		/* define the add-in bias for 16 bit.frames */
185#define uCLIP 32635
186
187static
188unsigned char ulaw_encode (int sample)
189{	static int exp_lut [256] =
190	{	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
191		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
192		5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
193		5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
194		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
195		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
196		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
197		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
198		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
199		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
200		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
201		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
202		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
203		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
204		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
205		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
206		} ;
207
208	int sign, exponent, mantissa ;
209	unsigned char ulawbyte ;
210
211	/* Get the sample into sign-magnitude. */
212	sign = (sample >> 8) & 0x80 ;					/* set aside the sign */
213	if (sign != 0)
214		sample = -sample ;							/* get magnitude */
215	if (sample > uCLIP)
216		sample = uCLIP ;							/* clip the magnitude */
217
218	/* Convert from 16 bit linear to ulaw. */
219	sample = sample + uBIAS ;
220	exponent = exp_lut [(sample >> 7) & 0xFF] ;
221	mantissa = (sample >> (exponent + 3)) & 0x0F ;
222	ulawbyte = ~ (sign | (exponent << 4) | mantissa) ;
223
224	return ulawbyte ;
225} /* ulaw_encode */
226
227
228/*
229** This routine converts from ulaw to 16 bit linear.
230**
231** Craig Reese: IDA/Supercomputing Research Center
232** 29 September 1989
233**
234** References:
235** 1) CCITT Recommendation G.711  (very difficult to follow)
236** 2) MIL-STD-188-113,"Interoperability and Performance Standards
237**     for Analog-to_Digital Conversion Techniques,"
238**     17 February 1987
239**
240** Input: 8 bit ulaw sample
241** Output: signed 16 bit linear sample
242*/
243
244static
245int ulaw_decode (unsigned int ulawbyte)
246{	static int exp_lut [8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 } ;
247	int sign, exponent, mantissa, sample ;
248
249	ulawbyte = ~ ulawbyte ;
250	sign = (ulawbyte & 0x80) ;
251	exponent = (ulawbyte >> 4) & 0x07 ;
252	mantissa = ulawbyte & 0x0F ;
253	sample = exp_lut [exponent] + (mantissa << (exponent + 3)) ;
254	if (sign != 0)
255		sample = -sample ;
256
257	return sample ;
258} /* ulaw_decode */
259
260