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