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 alaw_encode (int sample) ;
38 static int alaw_decode (unsigned int alawbyte) ;
39
40 static short short_buffer [BUFFER_SIZE] ;
41 static unsigned char alaw_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 ("alaw_test", "encoder") ;
51
52 filename = "alaw_test.raw" ;
53
54 sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ALAW, 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 alaw 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 alaw 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, alaw_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 (alaw_encode (short_buffer [k]) != alaw_buffer [k])
93 { printf ("Encoder error : sample #%d (0x%02X should be 0x%02X)\n", k, alaw_buffer [k], alaw_encode (short_buffer [k])) ;
94 exit (1) ;
95 } ;
96
97 sf_close (file) ;
98
99 puts ("ok") ;
100
101 print_test_name ("alaw_test", "decoder") ;
102 /* Now generate a file containing all possible 8 bit encoded
103 ** sample values and write it to disk as alaw encoded.frames.
104 */
105
106 if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
107 { printf ("sf_open_write failed with error : ") ;
108 puts (sf_strerror (NULL)) ;
109 exit (1) ;
110 } ;
111
112 for (k = 0 ; k < 256 ; k++)
113 alaw_buffer [k] = k & 0xFF ;
114
115 sf_write_raw (file, alaw_buffer, 256) ;
116 sf_close (file) ;
117
118 /* Now open that file and compare the alaw decoded sample values
119 ** with what they should be.
120 */
121
122 if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
123 { printf ("sf_open_write failed with error : ") ;
124 puts (sf_strerror (NULL)) ;
125 exit (1) ;
126 } ;
127
128 check_log_buffer_or_die (file, __LINE__) ;
129
130 if (sf_read_short (file, short_buffer, 256) != 256)
131 { printf ("sf_read_short : ") ;
132 puts (sf_strerror (file)) ;
133 exit (1) ;
134 } ;
135
136
137 for (k = 0 ; k < 256 ; k++)
138 if (short_buffer [k] != alaw_decode (alaw_buffer [k]))
139 { printf ("Decoder error : sample #%d (0x%02X should be 0x%02X)\n", k, short_buffer [k], alaw_decode (alaw_buffer [k])) ;
140 exit (1) ;
141 } ;
142
143 sf_close (file) ;
144
145 puts ("ok") ;
146
147 unlink (filename) ;
148
149 return 0 ;
150 } /* main */
151
152
153 /*=================================================================================
154 ** The following routines came from the sox-12.15 (Sound eXcahcnge) distribution.
155 **
156 ** This code is not compiled into libsndfile. It is only used to test the
157 ** libsndfile lookup tables for correctness.
158 **
159 ** I have included the original authors comments.
160 */
161
162 /*
163 ** A-law routines by Graeme W. Gill.
164 ** Date: 93/5/7
165 **
166 ** References:
167 ** 1) CCITT Recommendation G.711
168 **
169 */
170
171 #define ACLIP 31744
172
173 static
alaw_encode(int sample)174 unsigned char alaw_encode (int sample)
175 { static int exp_lut [128] =
176 { 1, 1, 2, 2, 3, 3, 3, 3,
177 4, 4, 4, 4, 4, 4, 4, 4,
178 5, 5, 5, 5, 5, 5, 5, 5,
179 5, 5, 5, 5, 5, 5, 5, 5,
180 6, 6, 6, 6, 6, 6, 6, 6,
181 6, 6, 6, 6, 6, 6, 6, 6,
182 6, 6, 6, 6, 6, 6, 6, 6,
183 6, 6, 6, 6, 6, 6, 6, 6,
184 7, 7, 7, 7, 7, 7, 7, 7,
185 7, 7, 7, 7, 7, 7, 7, 7,
186 7, 7, 7, 7, 7, 7, 7, 7,
187 7, 7, 7, 7, 7, 7, 7, 7,
188 7, 7, 7, 7, 7, 7, 7, 7,
189 7, 7, 7, 7, 7, 7, 7, 7,
190 7, 7, 7, 7, 7, 7, 7, 7,
191 7, 7, 7, 7, 7, 7, 7, 7
192 } ;
193
194 int sign, exponent, mantissa ;
195 unsigned char Alawbyte ;
196
197 /* Get the sample into sign-magnitude. */
198 sign = ((~sample) >> 8) & 0x80 ; /* set aside the sign */
199 if (sign == 0)
200 sample = -sample ; /* get magnitude */
201 if (sample > ACLIP)
202 sample = ACLIP ; /* clip the magnitude */
203
204 /* Convert from 16 bit linear to ulaw. */
205 if (sample >= 256)
206 { exponent = exp_lut [(sample >> 8) & 0x7F] ;
207 mantissa = (sample >> (exponent + 3)) & 0x0F ;
208 Alawbyte = ((exponent << 4) | mantissa) ;
209 }
210 else
211 Alawbyte = (sample >> 4) ;
212
213 Alawbyte ^= (sign ^ 0x55) ;
214
215 return Alawbyte ;
216 } /* alaw_encode */
217
218 static
alaw_decode(unsigned int Alawbyte)219 int alaw_decode (unsigned int Alawbyte)
220 { static int exp_lut [8] = { 0, 264, 528, 1056, 2112, 4224, 8448, 16896 } ;
221 int sign, exponent, mantissa, sample ;
222
223 Alawbyte ^= 0x55 ;
224 sign = (Alawbyte & 0x80) ;
225 Alawbyte &= 0x7f ; /* get magnitude */
226 if (Alawbyte >= 16)
227 { exponent = (Alawbyte >> 4) & 0x07 ;
228 mantissa = Alawbyte & 0x0F ;
229 sample = exp_lut [exponent] + (mantissa << (exponent + 3)) ;
230 }
231 else
232 sample = (Alawbyte << 4) + 8 ;
233 if (sign == 0)
234 sample = -sample ;
235
236 return sample ;
237 } /* alaw_decode */
238
239