2 ** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
29 #define BUFFER_SIZE (1<<14) /* Should be (1<<14) */
30 #define SAMPLE_RATE (11025)
33 #define M_PI 3.14159265358979323846264338
36 static void lcomp_test_int (const char *str
, const char *filename
, int filetype
, double margin
) ;
38 static int error_function (double data
, double orig
, double margin
) ;
39 static int decay_response (int k
) ;
41 static void gen_signal_double (double *data
, double scale
, int datalen
) ;
43 /* Force the start of these buffers to be double aligned. Sparc-solaris will
44 ** choke if they are not.
48 { double d
[BUFFER_SIZE
+ 1] ;
49 int i
[BUFFER_SIZE
+ 1] ;
52 static BUFFER data_buffer
;
53 static BUFFER orig_buffer
;
57 { const char *filename
= "test.au" ;
59 lcomp_test_int ("au_g721", filename
, SF_ENDIAN_BIG
| SF_FORMAT_AU
| SF_FORMAT_G721_32
, 0.06) ;
64 /*============================================================================================
65 ** Here are the test functions.
69 lcomp_test_int (const char *str
, const char *filename
, int filetype
, double margin
)
72 int k
, m
, *orig
, *data
, sum_abs
;
73 long datalen
, seekpos
;
76 printf ("\nThis is program is not part of the libsndfile test suite.\n\n") ;
78 printf (" lcomp_test_int : %s ... ", str
) ;
81 datalen
= BUFFER_SIZE
;
83 scale
= 1.0 * 0x10000 ;
85 data
= data_buffer
.i
;
86 orig
= orig_buffer
.i
;
88 gen_signal_double (orig_buffer
.d
, 32000.0 * scale
, datalen
) ;
89 for (k
= 0 ; k
< datalen
; k
++)
90 orig
[k
] = orig_buffer
.d
[k
] ;
93 sfinfo
.samplerate
= SAMPLE_RATE
;
94 sfinfo
.frames
= 123456789 ; /* Ridiculous value. */
96 sfinfo
.format
= filetype
;
98 if (! (file
= sf_open (filename
, SFM_WRITE
, &sfinfo
)))
99 { printf ("sf_open_write failed with error : ") ;
100 puts (sf_strerror (NULL
)) ;
104 if ((k
= sf_writef_int (file
, orig
, datalen
)) != datalen
)
105 { printf ("sf_writef_int failed with short write (%ld => %d).\n", datalen
, k
) ;
110 memset (data
, 0, datalen
* sizeof (int)) ;
112 if ((filetype
& SF_FORMAT_TYPEMASK
) != SF_FORMAT_RAW
)
113 memset (&sfinfo
, 0, sizeof (sfinfo
)) ;
115 if (! (file
= sf_open (filename
, SFM_READ
, &sfinfo
)))
116 { printf ("sf_open_read failed with error : ") ;
117 puts (sf_strerror (NULL
)) ;
121 if ((sfinfo
.format
& (SF_FORMAT_TYPEMASK
| SF_FORMAT_SUBMASK
)) != (filetype
& (SF_FORMAT_TYPEMASK
| SF_FORMAT_SUBMASK
)))
122 { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__
, filetype
, sfinfo
.format
) ;
126 if (sfinfo
.frames
< datalen
)
127 { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen
, SF_COUNT_TO_LONG (sfinfo
.frames
)) ;
131 if (sfinfo
.frames
> (datalen
+ datalen
/ 2))
132 { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen
, SF_COUNT_TO_LONG (sfinfo
.frames
)) ;
136 if (sfinfo
.channels
!= 1)
137 { printf ("Incorrect number of channels in file.\n") ;
141 check_log_buffer_or_die (file
, __LINE__
) ;
143 if ((k
= sf_readf_int (file
, data
, datalen
)) != datalen
)
144 { printf ("Line %d: short read (%d should be %ld).\n", __LINE__
, k
, datalen
) ;
149 for (k
= 0 ; k
< datalen
; k
++)
150 { if (error_function (data
[k
] / scale
, orig
[k
] / scale
, margin
))
151 { printf ("Line %d: Incorrect sample (#%d : %f should be %f).\n", __LINE__
, k
, data
[k
] / scale
, orig
[k
] / scale
) ;
152 oct_save_int (orig
, data
, datalen
) ;
155 sum_abs
= abs (sum_abs
+ abs (data
[k
])) ;
159 { printf ("Line %d: Signal is all zeros.\n", __LINE__
) ;
163 if ((k
= sf_readf_int (file
, data
, datalen
)) != sfinfo
.frames
- datalen
)
164 { printf ("Line %d: Incorrect read length (%ld should be %d).\n", __LINE__
, SF_COUNT_TO_LONG (sfinfo
.frames
- datalen
), k
) ;
168 /* This check is only for block based encoders which must append silence
169 ** to the end of a file so as to fill out a block.
171 if ((sfinfo
.format
& SF_FORMAT_SUBMASK
) != SF_FORMAT_MS_ADPCM
)
172 for (k
= 0 ; k
< sfinfo
.frames
- datalen
; k
++)
173 if (abs (data
[k
] / scale
) > decay_response (k
))
174 { printf ("Line %d : Incorrect sample B (#%d : abs (%d) should be < %d).\n", __LINE__
, k
, data
[k
], decay_response (k
)) ;
178 if (! sfinfo
.seekable
)
183 /* Now test sf_seek function. */
185 if ((k
= sf_seek (file
, 0, SEEK_SET
)) != 0)
186 { printf ("Line %d: Seek to start of file failed (%d).\n", __LINE__
, k
) ;
190 for (m
= 0 ; m
< 3 ; m
++)
193 if ((k
= sf_readf_int (file
, data
, 11)) != 11)
194 { printf ("Line %d: Incorrect read length (11 => %d).\n", __LINE__
, k
) ;
198 for (k
= 0 ; k
< 11 ; k
++)
199 if (error_function (data
[k
] / scale
, orig
[k
+ m
* 11] / scale
, margin
))
200 { printf ("Line %d: Incorrect sample (m = %d) (#%d : %d => %d).\n", __LINE__
, m
, k
+ m
* 11, orig
[k
+ m
* 11], data
[k
]) ;
201 for (n
= 0 ; n
< 1 ; n
++)
202 printf ("%d ", data
[n
]) ;
208 seekpos
= BUFFER_SIZE
/ 10 ;
210 /* Check seek from start of file. */
211 if ((k
= sf_seek (file
, seekpos
, SEEK_SET
)) != seekpos
)
212 { printf ("Seek to start of file + %ld failed (%d).\n", seekpos
, k
) ;
216 if ((k
= sf_readf_int (file
, data
, 1)) != 1)
217 { printf ("Line %d: sf_readf_int (file, data, 1) returned %d.\n", __LINE__
, k
) ;
221 if (error_function ((double) data
[0], (double) orig
[seekpos
], margin
))
222 { printf ("Line %d: sf_seek (SEEK_SET) followed by sf_readf_int failed (%d, %d).\n", __LINE__
, orig
[1], data
[0]) ;
226 if ((k
= sf_seek (file
, 0, SEEK_CUR
)) != seekpos
+ 1)
227 { printf ("Line %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %ld)\n", __LINE__
, k
, seekpos
+ 1) ;
231 seekpos
= sf_seek (file
, 0, SEEK_CUR
) + BUFFER_SIZE
/ 5 ;
232 k
= sf_seek (file
, BUFFER_SIZE
/ 5, SEEK_CUR
) ;
233 sf_readf_int (file
, data
, 1) ;
234 if (error_function ((double) data
[0], (double) orig
[seekpos
], margin
) || k
!= seekpos
)
235 { printf ("Line %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", __LINE__
, data
[0], orig
[seekpos
], k
, seekpos
+ 1) ;
239 seekpos
= sf_seek (file
, 0, SEEK_CUR
) - 20 ;
240 /* Check seek backward from current position. */
241 k
= sf_seek (file
, -20, SEEK_CUR
) ;
242 sf_readf_int (file
, data
, 1) ;
243 if (error_function ((double) data
[0], (double) orig
[seekpos
], margin
) || k
!= seekpos
)
244 { printf ("sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", data
[0], orig
[seekpos
], k
, seekpos
) ;
248 /* Check that read past end of file returns number of items. */
249 sf_seek (file
, (int) sfinfo
.frames
, SEEK_SET
) ;
251 if ((k
= sf_readf_int (file
, data
, datalen
)) != 0)
252 { printf ("Line %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__
, k
) ;
256 /* Check seek backward from end. */
257 if ((k
= sf_seek (file
, 5 - (int) sfinfo
.frames
, SEEK_END
)) != 5)
258 { printf ("sf_seek (SEEK_END) returned %d instead of %d.\n", k
, 5) ;
262 sf_readf_int (file
, data
, 1) ;
263 if (error_function (data
[0] / scale
, orig
[5] / scale
, margin
))
264 { printf ("Line %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%d should be %d).\n", __LINE__
, data
[0], orig
[5]) ;
271 } /* lcomp_test_int */
273 /*========================================================================================
274 ** Auxiliary functions
277 #define SIGNAL_MAXVAL 30000.0
278 #define DECAY_COUNT 800
281 decay_response (int k
)
283 return (int) (1.2 * SIGNAL_MAXVAL
) ;
286 return (int) (1.2 * SIGNAL_MAXVAL
* (DECAY_COUNT
- k
) / (1.0 * DECAY_COUNT
)) ;
287 } /* decay_response */
290 gen_signal_double (double *data
, double scale
, int datalen
)
294 ramplen
= datalen
/ 18 ;
296 for (k
= 0 ; k
< datalen
; k
++)
298 amp
= scale
* k
/ ((double) ramplen
) ;
299 else if (k
> datalen
- ramplen
)
300 amp
= scale
* (datalen
- k
) / ((double) ramplen
) ;
302 data
[k
] = amp
* (0.4 * sin (33.3 * 2.0 * M_PI
* ((double) (k
+ 1)) / ((double) SAMPLE_RATE
))
303 + 0.3 * cos (201.1 * 2.0 * M_PI
* ((double) (k
+ 1)) / ((double) SAMPLE_RATE
))) ;
307 } /* gen_signal_double */
310 error_function (double data
, double orig
, double margin
)
313 if (fabs (orig
) <= 500.0)
314 error
= fabs (fabs (data
) - fabs (orig
)) / 2000.0 ;
315 else if (fabs (orig
) <= 1000.0)
316 error
= fabs (data
- orig
) / 3000.0 ;
318 error
= fabs (data
- orig
) / fabs (orig
) ;
321 { printf ("\n\n*******************\nError : %f\n", error
) ;
325 } /* error_function */