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 
37 static unsigned char	ulaw_encode (int sample) ;
38 static int				ulaw_decode (unsigned int ulawbyte) ;
39 
40 static	short			short_buffer [BUFFER_SIZE] ;
41 static	unsigned char	ulaw_buffer [BUFFER_SIZE] ;
42 
43 int
main(void)44 main (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 = "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 
187 static
ulaw_encode(int sample)188 unsigned 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 
244 static
ulaw_decode(unsigned int ulawbyte)245 int 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