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